1

I go back over this subject

So I have this script :

    library(vegan)
    data(BCI) 
    df <- lapply(c(1,21,41,61,81),function(i)specaccum(BCI[,seq(i,i+19)], method="random"))
    par(mfrow=c(2,3))
    plot(df[[1]])
    for (i in 2:5) plot(df[[i]],add=F, col=i)

I wish to use ggplot instead of plot function. So I need facet_wrap to group all plots in one window.

But, I don't know how to use facet_wrap with the list df

Thanks for help

Community
  • 1
  • 1
Loulou
  • 703
  • 5
  • 17
  • This only works because there is a special function defined on `vegan` for objects of type `seecaccum` called `vegan:::plot.specaccum`. There's no way to convert that directly to `ggplot`. It's better to describe what exactly are your requirements for this new plot. – MrFlick Apr 11 '17 at 16:43

1 Answers1

0

In this case plotting is done via vegan:::plot.specaccum which makes direct calls to base plotting functions. This doesn't make it easy to directly plot these in ggplot. Here's a very hack-y function that attempts to replace the base drawing function can capture the parameters passed to them

snatch_specaccum_data <- function(x) {
    datalist <- list()
    data <- NULL
    grab_xy <- function(type) function(x,y,...) {datalist[[type]]<<- data.frame(x=x, y=y, type=type)}
    grab_xy2 <- function(type) function(x1,y1,x2,y2,...) {datalist[[type]]<<-data.frame(x1=x1,y1=y1,x2=x2,y2=y2, type=type)}
    plot <- function(...) {}
    lines <- grab_xy("line")
    polygon <- grab_xy("poly")
    segments <- grab_xy2("segment")
    myplot <- vegan:::plot.specaccum
    environment(myplot) <- environment()
    myplot(x)
    if (!is.na(datalist$line) && !is.na(datalist$segment)) {
       if(all(datalist$line$x == datalist$segment$x1) && all(datalist$segment$x1 == datalist$segment$x2)) {
         data <- cbind(datalist$line[,c("x","y")], datalist$segment[,c("y1","y2")])
       } else {
         stop("unable to match lines and segments")
       }
    } else {
       stop("didn't find lines and segments")
    }
    data
}

This allows us to extract the plot data for each of the specaccum in your list. We can combine them into a single data.frame with

dd <- dplyr::bind_rows(Map(snatch_specaccum_data, df), .id="source")

Then we can plot the data with

ggplot(dd) + 
    geom_line(aes(x,y, color=source)) + 
    geom_segment(aes(x,y1, xend=x, yend=y2, color=source)) + 
    facet_wrap(~source)

which gives you a plot pretty close to the base graphics version

enter image description here

MrFlick
  • 195,160
  • 17
  • 277
  • 295