-3

Can I use the arrow() function in R to plot a transparent arrow between two points that changes color? For example, an arrow that starts out as red at one point, and gradually changes to blue at the other point (both points are on the same row in a dataframe)? If so, how? And if not, is there another function that can do that in R?

Here is the piece of code I have until now, which draws points (blue and red) and connects the blue points with the red points with transparent blue arrows:

par(xpd=NA, mfrow=c(1,1), mar=c(4.25,3.2,6.20,3.55))
plot(data$x1,data$y1,col="red",pch=20,cex=0.6,xlim=c(xmin,xmax),ylim=c(ymin,ymax),axes=FALSE,ann=FALSE,xaxt='n',yaxt='n')
par(new=T)
plot(data$x2,data$y2,col="blue",pch=20,cex=0.6,xlim=c(xmin,xmax),ylim=c(ymin,ymax),axes=FALSE,ann=FALSE,xaxt='n',yaxt='n')
par(new=T)
plot(grid.picture(NLmap[-1]),xlim=c(xmin,xmax),ylim=c(ymin,ymax),axes=FALSE,ann=FALSE,xaxt='n',yaxt='n')
par(new=T)

points(data$x1,data$y1,col="red",pch=20,cex=0.25)
par(new=T)
points(data$x2,data$y2,col="blue",pch=20,cex=0.25)
par(new=T)

arrows(data$x1,data$y1, data$x2, data$y2, length = 0.05, angle = 30, 
   code = 2, col = "#9AC0CD40", lty = par("lty"), lwd = par("lwd"))

Hope this helps!

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Abdel
  • 5,826
  • 12
  • 56
  • 77
  • This question is very similar to [an earlier question](http://stackoverflow.com/questions/11058072/create-an-arrow-with-gradient-color) – Justin Jun 19 '12 at 18:56
  • Thanks, I'll check what I can do with those answers. I'm afraid however that those are not the kind of arrows I'm looking for. I got a lot of pairs of points that I want to connect with a arrow similar to the one that the arrow() function draws. I got the plot looking just right with the arrow() function, except for the color change... – Abdel Jun 19 '12 at 19:11
  • If you show your data and the code you are currently using, you're much more likely to get a good answer. you can use `dput(yourdata)` and paste its output. – Justin Jun 19 '12 at 19:13
  • Thanks, I put the code I have until now! Hope that helps! Unfortunately I don't have permission to share the data... – Abdel Jun 20 '12 at 08:08
  • Can you make up some data similar to the problem you're tying to solve? Usually people here don't need your exact data, just something representative of your data. What type of content can be found in `data$x1`, `data$y1`, and so on? – A5C1D2H2I1M1N2O1R2T1 Jun 28 '12 at 06:14
  • As mentioned in the earlier comments, you should really provide example data along with your code. It is difficult to understand what is going on without the values of `data`. Also, you should simplify your example to highlight only the question; what is the point of plotting the Netherlands in reference to this question? – nograpes Jun 29 '12 at 21:16
  • 3
    providing **reproducible code** as people requested is a much stronger incentive than bounties, think about it. – baptiste Jun 29 '12 at 22:38
  • Thanks, I'll keep that in mind for the next time! – Abdel Jul 02 '12 at 09:40

2 Answers2

3

First of all, I should mention that my answer is directly derived from the information provided in the comments and the answer by DWin. I had never seen those functions before, so I thought I would give them a shot.

I ended up creating a little function that works like arrows except a colour scale is added. I think this is essentially what you want.

require(plotrix)

color.scale.arrow = function(x1,y1,x2,y2,first.col,second.col,
lwd= par('lwd'),lty=par('lty'),angle=30,length=0.25) {
        x=mapply(seq,x1,x2,length.out=256) # Each column is one arrow
        y=mapply(seq,y1,y2,length.out=256) # Each column is one arrow

        arrows(x[255,],y[255,],x[256,],y[256,],
               col=ifelse(y[256,]<y[255,],first.col,second.col),
               lwd=lwd,lty=lty,angle=angle,length=length)

        rgb1=col2rgb(first.col)[,1] / 255
        rgb2=col2rgb(second.col)[,1] / 255
        cols=rbind(rgb1,(rgb1 + rgb2) / 2,rgb2)

        invisible(
              sapply(seq(ncol(x)),function(line) 
                  color.scale.lines(x[,line],y[,line],
                  cols[,'red'],cols[,'green'],cols[,'blue'],
                  lwd=lwd,lty=lty)
              )
       )
}

# Create sample data
set.seed(1)
x <- runif(12); y <- rnorm(12)
i <- order(x,y); x <- x[i]; y <- y[i]
x1=x[s]
x2=x[s+1]
y1=y[s]
y2=y[s+1]

# Plot sample data
plot(x,y, main='', type='n')
color.scale.arrow(x1,y1,x2,y2,'red','blue',lwd=2)

Sample Arrow Plot

The arrow head will have a colour that matches the 'end' colour given in color.scale.arrow.

nograpes
  • 18,623
  • 1
  • 44
  • 67
  • Thank you very much! My R-skills aren't that developed yet, so thanks for showing me how to build that function. – Abdel Jul 02 '12 at 09:41
2

I realize that you already looked at the other page cited by Justin, but believe that had you posted a workable example using segments that we would have been able to modify it to use the plotrix::color.scale.lines function. After all the arrows function is very similar to the call to segments.

IRTFM
  • 258,963
  • 21
  • 364
  • 487
  • a crucial point here is whether the OP wants the tip of the arrow to have a gradient too, I think. – baptiste Jun 19 '12 at 19:42
  • True enough. Perhaps he will include that detail in his response. – IRTFM Jun 19 '12 at 19:51
  • I'd like the tip of the arrow to be completely red if the arrow starts out as blue... – Abdel Jun 20 '12 at 08:09
  • And thanks for the color.scale.lines function. I can only get it to connect all points however (and I only want pairs of points to be connected), and I don't understand how to apply the color change to the arrows... – Abdel Jun 20 '12 at 08:32