0

I am not sure exactly how to override aesthetic properties of a custom plot made with ggplot. The only way I could think of right now was using the functionality of the grid package, though is really hackish. Maybe there is a easier way, like using guides or so from ggplot2, though I could't manage to make it work?

Below is an example where I just want to adjust the line width in the graph. Of course, I would like that to trickle down in the legend as well. So, below are my steps with grid, but any simpler solution is greatly appreciated (ideally something that doesn't need grid but just ggplot2, if possible).

library(iNEXT)
library(ggplot2)
library(grid)

# Some custom plot from the iNEXT package
data(spider)
out <- iNEXT(spider, q=0, datatype="abundance")

custom_plot <- ggiNEXT(out)
custom_plot

# Get the grobs
g <- grid.force(ggplotGrob(custom_plot))

# Check the list of names of grobs:
# grid.ls(g) 
# View(g$grobs)

# Get an idea about the grob paths
gpaths <- paste(gsub(pattern = "layout::", 
                     replacement = "", 
                     x = grid.ls(g, print = FALSE)$gPath), 
                grid.ls(g, print = FALSE)$name, 
                sep = "::")
gpaths[grepl("polyline", gpaths)]
#> [1] "panel.7-5-7-5::grill.gTree.114::panel.grid.minor.y..polyline.107"            
#> [2] "panel.7-5-7-5::grill.gTree.114::panel.grid.minor.x..polyline.109"            
#> [3] "panel.7-5-7-5::grill.gTree.114::panel.grid.major.y..polyline.111"            
#> [4] "panel.7-5-7-5::grill.gTree.114::panel.grid.major.x..polyline.113"            
#> [5] "panel.7-5-7-5::GRID.polyline.91"                                             
#> [6] "panel.7-5-7-5::geom_ribbon.gTree.101::geom_ribbon.gTree.95::GRID.polyline.93"
#> [7] "panel.7-5-7-5::geom_ribbon.gTree.101::geom_ribbon.gTree.99::GRID.polyline.97"

# Edit the width of the lines
g <- editGrob(grob = g, 
              gPath = gpaths[grepl("panel.7-5-7-5::GRID.polyline", gpaths)],
              gp = gpar(lwd = c(1,1,1,1)))
plot(g)

Created on 2020-07-22 by the reprex package (v0.3.0)

Valentin_Ștefan
  • 6,130
  • 2
  • 45
  • 68

2 Answers2

2

The answer you are looking for is under "Draw R/E curves by yourself" at https://cran.r-project.org/web/packages/iNEXT/vignettes/Introduction.html.

Fortunately, the authors of the package have provided the function fortify() along with some code to copy verbatim, to achieve what you desire.

You should copy the following from that section and change the lwd (line width) parameter in the geom_line() function call to your liking.

df <- fortify(out, type=1) # Note the type parameter!

df.point <- df[which(df$method=="observed"),]
df.line <- df[which(df$method!="observed"),]
df.line$method <- factor(df.line$method, 
                         c("interpolated", "extrapolated"),
                         c("interpolation", "extrapolation"))
 
ggplot(df, aes(x=x, y=y, colour=site)) + 
  geom_point(aes(shape=site), size=5, data=df.point) +
  geom_line(aes(linetype=method), lwd=1.5, data=df.line) +
  geom_ribbon(aes(ymin=y.lwr, ymax=y.upr,
                  fill=site, colour=NULL), alpha=0.2) +
  labs(x="Number of individuals", y="Species diversity") +
  theme(legend.position = "bottom", 
        legend.title=element_blank(),
        text=element_text(size=18),
        legend.box = "vertical") 
1

I think you're making life overly complicated. Does this approach gives you what you need?

Generate a plot

plot <- mtcars %>% ggplot() + geom_line(aes(x=mpg, y=cyl, colour=as.factor(gear)))
plot

original plot

Modify the plot

plot + aes(size=5) + guides(size=FALSE)

modified plot

The guides call suppresses the legend for size. Obviously, you can delete it if you do want the legend to appear.

Update

Responding to OP's question in the comments. I agree: my suggestion does not modify the ggiNEXT plot as I predicted.

I've done some digging. The diversity curves in the plot are produced by the following statement in the ggiNEXT.iNEXT function

g <- g + geom_line(aes_string(linetype = "lty"), lwd = 1.5) + ...

I find this strange. As far as I know, lwd is not an aesthetic in ggplot2. (And "lty" is not a valid value for the linetype aesthetic. However, lty and lwd are the base R equivalents of ggplot2's linetype and size respectively.)

In case lwd was an undocumented feature, I tried

custom_plot + aes(lwd=3)

But this had no effect.

I then copied the body of the ggiNEXT.iNEXT function into my own function and changed the call to geom_line to read

g <- g + geom_line(aes_string(linetype = "lty"), size = 1.5)

Calling my new function produced a plot identical (to my eye at least) to that produced by the original ggiNEXT.iNEXT call. Then

custom_plot <- myPlot(out)
custom_plot
custom_plot + aes(size=3) + guides(size=FALSE)

Produced the predicted changes. So my best suggestion is either (1) to create a local version of ggiNEXT.iNEXT and load it whenever you need to make this modification [Of course, you then need to make sure you update your local copy in line with any changes to the "official" version] or (2) to create the graph from scratch. Looking at the source code for ggiNEXT.iNEXT, it's not that complicated.

This might be worth raising as an issue with the authors of iNEXT.

Limey
  • 10,234
  • 2
  • 12
  • 32
  • Hi @Limey, have you tried your proposed solution on the provided iNEXT custom plot? I purposely created that example. I don't seem to get the expected results. – Valentin_Ștefan Jul 22 '20 at 13:41
  • 1
    Valentin, no, I haven't. Simply because I didn't spot that your input data was a package dataset. Apologies. I don't have the iNEXT package installed, but I will see what I can do. – Limey Jul 22 '20 at 13:52