0

I generate a multipanel plot using ggplot2 (requires ggplot2 package). Each of the ten panels represents a different plant growth form. I need to plot a line in each panel that has a slope of 0.704. However, the intercept should be different for each panel, for example -7.9 in the case of 'fern', -7.31 for 'fern ally', etc. Currently, I use the code below which generates a line where both slope and intercept are the same in each panel:

ggplot(veg, aes(x=ord1, y=log(lai+0.000019))) +    
scale_x_discrete(limits=c("1","2","3","4","5","6","7","8","9")) +
scale_y_continuous(limits=c(-12,3)) +
geom_point(shape=1) +
geom_segment(aes(x = 1, xend = 9, y = -8.32 + .704, yend = -8.32 + .704*9), 
           col = "black", size = 1, lty="longdash", lwd=1) +
facet_wrap( ~ plant_growth_form, ncol=5) 

How could I modify this code in ggplot2 to specify a different intercept for each growth form?

A reproducible data subset generated with dput() can be found at: How to compute standard errors for predicted data

Community
  • 1
  • 1
tabtimm
  • 411
  • 3
  • 6
  • 17

1 Answers1

1

First, create a separate data frame housing intercepts and slope. e.g. "a" is intercepts, "b" is the slope. We call this data frame "df3".

df3 <- data.frame(plant_growth_form = unique(veg[,3]),
                  a = c(-10,-9,-8,-7,-6,-5,-4,-3,-2,-1), # assigned arbitrarily
                  b= 0.704)

#     plant_growth_form   a     b
# 1                herb -10 0.704
# 2                moss  -9 0.704
# 3       woody climber  -8 0.704
# 4        tree sapling  -7 0.704
# 5                fern  -6 0.704
# 6  herbaceous climber  -5 0.704
# 7               undet  -4 0.704
# 8    herbaceous shrub  -3 0.704
# 9               grass  -2 0.704
# 10        woody shrub  -1 0.704

to plot

ggplot(veg, aes(x=ord1, y=log(lai+0.000019))) +    
  scale_x_discrete(limits=c("1","2","3","4","5","6","7","8","9")) +
  scale_y_continuous(limits=c(-12,3)) +
  geom_point(shape=1) +
  geom_abline(aes(intercept=a, slope=b), data=df3) +
  facet_wrap( ~ plant_growth_form, ncol=5)

enter image description here

update the tweak per @aosmith's comment.

# you could separately modify the dataframe of intercepts & slope, or
# adjust directly in the code below for small data (see <--)
df3 <- data.frame(plant_growth_form = unique(veg[,3]),
                  a = c(-10,-9,-8,-7,-6,-5,-4,-3,-2,-1),  # <-- here
                  b= 0.704)                               # <-- here

# to add the code of extra segment (see <--), in red.
ggplot(veg, aes(x=ord1, y=log(lai+0.000019))) +    
  scale_x_discrete(limits=c("1","2","3","4","5","6","7","8","9")) +
  scale_y_continuous(limits=c(-12,3)) +
  geom_point(shape=1) +
  #geom_abline(aes(intercept=a, slope=b), data=df3) +
  geom_segment(data = df3, aes(x = 1, xend = 9, y = a + b, yend = a + b*9)) +
  geom_segment(aes(x = 1, xend = 9, y = -8.32 + .704, yend = -8.32 + .704*9), # <-- here
               col = "red", size = 1, lty="longdash", lwd=1) +
  facet_wrap( ~ plant_growth_form, ncol=5) 

enter image description here

KFB
  • 3,501
  • 3
  • 15
  • 18
  • KFB, that works great, would it be possible to tweak the code so that the line starts at x=1 and stops at x=9, similar to the original: geom_segment(aes(x = 1, xend = 9, y = -8.32 + .704, yend = -8.32 + .704*9), i.e. replacing -8.32 with a and 0.704 with b? – tabtimm Oct 14 '14 at 08:13
  • @tabtimm, you meant to add more line to existing graph? that'd be quite messy. – KFB Oct 14 '14 at 08:18
  • maybe that was confusing, I did not mean to reintegrate the code for the above dashed red line but to give a start point of x=1 and endpoint of x=9 to the lines with the different intercepts that you generated. – tabtimm Oct 14 '14 at 08:45
  • @tabtimm, Don't get it. The lines do span from 1 to 9 on x-axis. – KFB Oct 14 '14 at 08:49
  • I was hoping that the thin black lines in the above multipanel graph would start at x=1 and stop at x=9. At the moment, they span the whole width of the graph. – tabtimm Oct 14 '14 at 08:55
  • KFB, thanks for the continuous input. Seems like a nice idea to reduce the width of the x-axis, however, to keep the original width with that extra bit to the left of x=1 and to the right of x=9 would be preferable, otherwise the output looks strange with those points at x=1 and x=9 being halved. Maybe your proposed function geom_abline(aes(intercept=a, slope=b), data=df3) could be modified to a geom_segment function that allows for specifying the range of the line? – tabtimm Oct 14 '14 at 12:41
  • If need that extra space, just take away expand=c(0, 0). Is the cosmetic difference worthy of the effort ? :) Unable to modify geom_segment for that purpose. – KFB Oct 14 '14 at 12:48
  • 1
    To use just `geom_segment` instead of `geom_abline`, you could do `geom_segment(data = df3, aes(x = 1, xend = 9, y = a + b, yend = a + b*9))` – aosmith Oct 14 '14 at 15:09
  • Brilliant, exactly what I was hoping for. – tabtimm Oct 16 '14 at 01:55