Skip to content

Rarefaction curves in ggplot

3 messages · Drew Tyre, Roman Luštrik, Ellen Pape

#
Hi Ellen,

I was curious about this because I will be using a lot of vegan functions in a spring class. Turns out not to be trivial - as with all ggplot problems the trick is to get the data into a dataframe. I tried several things, but ended up writing my own function:

# rarefraction curves and ggplot
library("tidyverse")
library("vegan")
data(BCI)
out <- rarecurve(BCI, step = 10, sample = 400)
names(out) <- 1:50

as_tibble_rc <- function(x){
  # convert rarecurve() output to data.frame
  # bind_rows doesn't work because items are different lengths
  # also need to extract sample sizes from attribute 
  # Allocate result dataframe
  nsamples <- map_int(x, length)
  total_samples <- sum(nsamples)
  if(!is.null(names(x))){
    sites <- names(x)
  } else {
    sites <- as.character(1:length(nsamples))
  }
  result <- data_frame(Site = rep("", total_samples),
                       Sample_size = rep(0, total_samples),
                       Species = rep(0, total_samples))
  start <- 1
  for (i in 1:length(nsamples)){
    result[start:(start + nsamples[i]-1), "Site"] <- sites[i]
    result[start:(start + nsamples[i]-1), "Sample_size"] <- attr(x[[i]], "Subsample")
    result[start:(start + nsamples[i]-1), "Species"] <- x[[i]]
    start <- start + nsamples[i]
  }
  result
}

out <- as_tibble_rc(out)
# add grouping variable
sitedata <- data_frame(Site = as.character(1:50),
                       Type = sample(LETTERS[1:2], 50, replace = TRUE))
alldata <- left_join(out, sitedata, by = "Site")

# and then it's trivial
ggplot(data = alldata,
       mapping = aes(x = Sample_size, y = Species, color = Type, group = Site)) + 
  geom_line()

hope that helps.
#
I don't think it's that critical. It's just a matter of coercing the data
into a long format. And loading the entire tidyverse isn't really necessary
since we need one package from that bundle. I present a bonus feature using
plotly (see at the bottom).

library(vegan)
library(ggplot2)
library(plotly)

data(BCI)
out <- rarecurve(BCI, step = 10, sample = 400, label = FALSE)
names(out) <- paste("species", 1:50, sep = "")

# Coerce data into "long" form.
protox <- mapply(FUN = function(x, y) {
  mydf <- as.data.frame(x)
  colnames(mydf) <- "value"
  mydf$species <- y
  mydf$subsample <- attr(x, "Subsample")
  mydf
}, x = out, y = as.list(names(out)), SIMPLIFY = FALSE)

xy <- do.call(rbind, protox)
rownames(xy) <- NULL  # pretty

# Plot.
ggplot(xy, aes(x = subsample, y = value, color = species)) +
  theme_bw() +
  scale_color_discrete(guide = FALSE) +  # turn legend on or off
  geom_line()

Since exploring this mikado of lines can be hard, we can make the plot
interactive. Try hovering over the lines. Presto!

ggplotly(
  ggplot(xy, aes(x = subsample, y = value, color = species)) +
    theme_bw() +
    theme(legend.position = "none") +  # ggplotly doesn't respect scales?
    geom_line()
)

Cheers,
Roman
On Mon, Dec 17, 2018 at 6:58 PM Drew Tyre <atyre2 at unl.edu> wrote:

            

  
    
#
Thanks, Roman and Drew!! Both options work!

cheers,
ellen
On Mon, 17 Dec 2018 at 18:58, Drew Tyre <atyre2 at unl.edu> wrote: