3

I would really appreciate the assistance of the helpful community in this forum with a little issue I'm having with R, and the arrow function when trying to draw error bars. I chose to use the arrows function to generate my error bars for their simplicity in adding to the graphs I've already created.

I've been successful in drawing two scatterplots for the following table using plot()

     X sitting.time exercise.time se.sit.time se.ex.time
     1     535.7308      70.08000    45.39388   13.23958
     2     512.8800      65.80000    50.92198   13.98714
     3     500.2727      80.09091    47.00300   13.90255
     4     504.4762      77.35000    48.38485   17.22151
     5     487.0588      84.00000    51.62004   14.62120
     6     487.3333      83.53333    51.15082   17.52736
     7     462.5294      83.52941    49.97000   17.61185
     8     458.1111      71.78947    47.30922   12.64716
     9     471.9333      73.66667    57.13613   16.97271
    10     517.1333      84.92857    62.34817   18.61450
    11     526.5625      73.93750    50.25767   17.67990
    12     484.0000      96.22222    73.67854   23.97266

In the table, sitting.time and exercise.time are my y-values, X are x-values, and se.sit.time and se.ex.time are standard errors.

The commands I've successfully used to generate two plots (including legend) are as follows:

plot(weekly.times$X,weekly.times$sitting.time,
 xlim=c(1,12),ylim=c(0,600),
 xaxt="n", yaxt="n",xlab="Week", 
 ylab="Time (minutes)", type="p",col="red")
 axis(side=1,at=c(1:12))
 axis(side=2,at=seq(0,600,by=50))
 lines(weekly.times$X,weekly.times$sitting.time, 
   xlab="Week", ylab="Time", col="red")
 par(new=TRUE)
 plot(weekly.times$X,weekly.times$exercise.time, 
  xlab='', ylab='', axes=FALSE, col="blue")
 lines(weekly.times$X,weekly.times$exercise.time, 
   xlab='', ylab='', col="blue")
 legend("bottom",inset=c(-0.3,0), 
     legend=c("Sitting Time", "Exercise Time"), 
     col=c("red", "blue"), lty=1:2, cex=0.8)

However, after trying to add the arrows() after the first plot, I do not see any error bars generated in the same way as the original answer to a similar post on the topic: Scatter plot with error bars

arrows(weekly.times$sitting.time, sitCI.down, 
  weekly.times$sitting.time, sitCI.up, length=0.05, angle=90, code=3)

My output for the first plot, where I would like to add error bars. I've also run the arrows function after this plot:

enter image description here

My output with both plots in a graph. I would eventually like both graphs to have error bars. I've also tried to run arrows() here without avail:

enter image description here

Does anyone know what I might be doing wrong, and why the error plots are not showing up in the graphic?


After following @rbatt 's solution, I got the graph to work with error plots as below:

enter image description here

I used the following code:

p1.ylim <- range(c(weekly.times$sitting.time, sitCI.down, sitCI.up))
p1.xlim <- range(weekly.times$X)
par(mar=c(4,4,0.5,4))
plot(weekly.times$X, weekly.times$sitting.time, xlim=p1.xlim, ylim=p1.ylim, ylab="Sitting Time (minutes)", xlab="Week", type="o",col="red", xaxt="n", yaxt="n")
axis(side=1,at=weekly.times$X)
axis(side=2,at=seq(p1.ylim[1],p1.ylim[2],by=50))
red2 <- adjustcolor("red", alpha.f=0.25)
arrows(weekly.times$X, sitCI.down, weekly.times$X, sitCI.up, length=0.05, angle=90, code=3, col=red2)
par(new=TRUE)
plot(weekly.times$X,weekly.times$exercise.time, xlab='', ylab='', axes=FALSE, col="blue", type="o")
axis(side=4)
blue2 <- adjustcolor("blue", alpha.f=0.25)
arrows(weekly.times$X, exCI.down, weekly.times$X, exCI.up, length=0.05, angle=90, code=3, col=blue2)
mtext("Exercise Time (minutes)", side=4, line=3)
legend("bottom",inset=c(-0.3,0), legend=c("Sitting Time", "Exercise Time"), col=c("red", "blue"), lty=1:2, cex=0.8)

However, I now have new data as follows, which does not get the error bars to fit.

week sitting.time exercise.time se.sit.time se.ex.time
1     1     3643.087      471.5833    349.5165   98.06667
2     2     3516.478      472.7917    337.8359   99.83149
3     3     3373.000      535.6667    344.9220  103.70350
4     4     3480.952      510.2857    352.2140  118.32880
5     5     3235.882      571.3529    345.0725  104.53620
6     6     3359.000      587.1333    349.3253  122.10290
7     7     3246.250      554.1250    358.0210  131.71030
8     8     3173.889      502.7895    326.9745   88.58391
9     9     3438.643      513.0667    354.2999  119.08770
10   10     3581.154      807.7143    323.0524  230.90890
11   11     3661.250      693.7059    357.1707  212.60630
12   12     3297.500      909.0000    589.6690  276.65540

And using the same code I get the following plot:

enter image description here

Do you know where in the axis code I went wrong which causes the error bars for the blue line to not show?

Thank you.

Community
  • 1
  • 1
Avi
  • 53
  • 1
  • 4
  • 1
    use `dput()` on your data so we can recreate the graph you see now – rbatt Jun 30 '15 at 13:24
  • I've just added links to the images - sorry I don't have enough reputation points yet to embed them – Avi Jul 01 '15 at 14:33
  • I just embedded them, they'll show up after edit review – C8H10N4O2 Jul 01 '15 at 14:37
  • Thank you, C8H10N4O2 :) – Avi Jul 01 '15 at 15:56
  • @rbatt Hi. While your solution was perfect, I've encountered an issue with new data and plotting the error bars that might have to do with new axes. I've played around with the code but to no avail. Any help would be greatly appreciated. – Avi Jul 07 '15 at 20:08
  • @rbatt Still stuck. Any help would be appreciated :) – Avi Jul 22 '15 at 01:58
  • Maybe try asking a new question if this is separate from the original. Also, I'm typically not too keen on repeatedly debugging code; that's not the purpose. Someone correct me if I'm wrong. – rbatt Jul 27 '15 at 13:45

1 Answers1

1

There are two main problems that you had. First, you provided a y-axis variable, weekly.times$sitting.time, to the x0 and x1 arguments of arrows(); I've changed these to be weekly.times$X, which is the week, which is on your x-axis. Second, you were trying to add the arrows after your call to par(new=TRUE) and your addition of the exercise time, which has a range between ~60 and ~100, and because ylim was not set and your arrows are in the 500-600 range, they would have been created way off the plot (even if the first issue had been resolved).

Below is code that makes minimal changes to your original code in order to generate suitable figures. Note that you did not provide the data for the objects sitCI.down and sitCI.up, so I just did a ±10% around the sitting times. Also, I first include the output of a dput() on a data.frame that I manually copied from your question; in the future, it would make reproducing your results much easier if you would use dput() on your data and copy the output into your question.

Create data set using output from dput

weekly.times <- structure(list(X = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), 
    sitting.time = c(535.7308, 512.88, 500.2727, 504.4762, 487.0588, 
    487.3333, 462.5294, 458.1111, 471.9333, 517.1333, 526.5625, 
    484), exercise.time = c(70.08, 65.8, 80.09091, 77.35, 84, 
    83.53333, 83.52941, 71.78947, 73.66667, 84.92857, 73.9375, 
    96.22222), se.sit.time = c(45.39388, 50.92198, 47.003, 48.38485, 
    51.62004, 51.15082, 49.97, 47.30922, 57.13613, 62.34817, 
    50.25767, 73.67854), se.ex.time = c(13.23958, 13.98714, 13.90255, 
    17.22151, 14.6212, 17.52736, 17.61185, 12.64716, 16.97271, 
    18.6145, 17.6799, 23.97266)), .Names = c("X", "sitting.time", 
"exercise.time", "se.sit.time", "se.ex.time"), row.names = c(NA, 
-12L), class = "data.frame")

Generate desired plots with minimal changes to original code

plot(weekly.times$X, weekly.times$sitting.time, xlim=c(1,12), ylim=c(0,600), ylab="Time (minutes)", type="p",col="red")
axis(side=1,at=c(1:12))
axis(side=2,at=seq(0,600,by=50))
lines(weekly.times$X, weekly.times$sitting.time, xlab="Week", ylab="Time", col="red")

sitCI.down <- weekly.times$sitting.time + c(-0.1)*weekly.times$sitting.time
sitCI.up <-  weekly.times$sitting.time + c(0.1)*weekly.times$sitting.time
arrows(weekly.times$X, sitCI.down, weekly.times$X, sitCI.up, length=0.05, angle=90, code=3)

par(new=TRUE)
plot(weekly.times$X,weekly.times$exercise.time, xlab='', ylab='', axes=FALSE, col="blue")
lines(weekly.times$X,weekly.times$exercise.time, xlab='', ylab='', col="blue")
legend("bottom",inset=c(-0.3,0), legend=c("Sitting Time", "Exercise Time"), col=c("red", "blue"), lty=1:2, cex=0.8)

enter image description here

So the above code should solve your problem. However, I'd like to provide a little extra help/ style advice with regard to your figure. See code below.

A cleaner, more condensed approach (my opinion)

# Calculate CI's first to account for them in ylim of plot
sitCI.down <- weekly.times$sitting.time + c(-0.1)*weekly.times$sitting.time
sitCI.up <-  weekly.times$sitting.time + c(0.1)*weekly.times$sitting.time

# I very frequently follow this idiom for making sure the ylims are set properly
# It is better to define ylims programmatically than by using magic numbers like c(0,600)
p1.ylim <- range(c(weekly.times$sitting.time, sitCI.down, sitCI.up))
p1.xlim <- range(weekly.times$X) # same idea for xlim, but simpler case

# When creating your plot, you can set type="o" do draw the points and the lines at the same time
# Also, if you're going to create the axes with axis(), you can also not draw them in the plot
# Turn axes off using xaxt="n" and yaxt="n"
# Finally, if you are going to use par(new=TRUE), you are creating an 
# independent y-axis, and you should leave room in the right margin to draw it
par(mar=c(4,4,0.5,4))
plot(weekly.times$X, weekly.times$sitting.time, xlim=p1.xlim, ylim=p1.ylim, ylab="Sitting Time (minutes)", xlab="Week", type="o",col="red", xaxt="n", yaxt="n") # I would also change the axis label

# When drawing axes, avoid magic numbers
axis(side=1,at=weekly.times$X)
axis(side=2,at=seq(p1.ylim[1],p1.ylim[2],by=50))

# When drawing the errors, you might want to keep the color of the line
# but maybe make it a bit lighter so it isn't easily confused
# making the error bars fainter makes the figure much easier on the eyes
red2 <- adjustcolor("red", alpha.f=0.25)
arrows(weekly.times$X, sitCI.down, weekly.times$X, sitCI.up, length=0.05, angle=90, code=3, col=red2)

par(new=TRUE)
# again in this plot, just use type="o" to accomplish in 1 line what you're doing in 2
plot(weekly.times$X,weekly.times$exercise.time, xlab='', ylab='', axes=FALSE, col="blue", type="o")
axis(side=4) # add the axis for the blue line
mtext("Exercise Time (minutes)", side=4, line=3)
legend("bottom",inset=c(-0.3,0), legend=c("Sitting Time", "Exercise Time"), col=c("red", "blue"), lty=1:2, cex=0.8)

enter image description here

rbatt
  • 4,677
  • 4
  • 23
  • 41
  • This is perfect, and thanks so much for the clear walkthrough! – Avi Jul 01 '15 at 20:55
  • Hi @rbatt I've had new data that now no longer works with the solution - my error bars don't show up any more for the second graph. I realize it is something to do with the range of my y-axis but after trying all solutions I can think of I can't get the error bars to show. I've added my issue below my original question. Any help would be greatly appreciated! Thanks. – Avi Jul 07 '15 at 19:47