Search code examples
rggplot2labelmultivariate-testingautoplot

DCA : Labelling points with autoplot or ggplot2


I find very difficult to put labels for sites with a DCA in a autoplot or ggplot.
I also want to differentiate the points on the autoplot/ggplot according to their groups.
This is the data and the code I used and it went well until the command for autoplot/ggplot:

library(vegan)
data(dune)
d <- vegdist(dune)
csin <- hclust(d, method = "single")
cl <- cutree(csin, 3)
dune.dca <- decorana(dune)
autoplot(dune.dca)

This is the autoplot obtained:

dca_autoplot

I am using simple coding and I tried these codes but they didn't led me anywhere:

autoplot(dune.dca, label.size = 3, data = dune, colour = cl)
ggplot(dune.dca(x=DCA1, y=DCA2,colour=cl))
ggplot(dune.dca, display = ‘site’, pch = 16, col = cl)
ggrepel::geom_text_repel(aes(dune.dca))

If anyone has a simple suggestion, it could be great.


Solution

  • With the added information (package) I was able to go and dig a bit deeper.

    The problem is (in short) that autoplot.decorana adds the data to the specific layer (either geom_point or geom_text). This is not inherited to other layers, so adding additional layers results in blank pages.

    Basically notice that one of the 2 code strings below results in an error, and note the position of the data argument:

    # Error: 
    ggplot() + 
      geom_point(data = mtcars, mapping = aes_string(x = 'hp', y = 'mpg')) +
      geom_label(aes(x = hp, y = mpg, label = cyl))
    # Work:
    ggplot(data = mtcars) + 
      geom_point(mapping = aes_string(x = 'hp', y = 'mpg')) +
      geom_label(aes(x = hp, y = mpg, label = cyl))
    

    ggvegan:::autoplot.decorana places data as in the example the returns an error.

    I see 2 ways to get around this problem:

    1. Extract the layers data using ggplot_build or layer_data and create an overall or single layer mapping.
    2. Extract the code for generating the data, and create our plot manually (not using autoplot).

    I honestly think the second is simpler, as we might have to extract more information to make our data sensible. By looking at the source code of ggvegan:::autoplot.decorana (simply printing it to console by leaving out brackets) we can extract the below code which generates the same data as used in the plot

    ggvegan_data <- function(object, axes = c(1, 2), layers = c("species", "sites"), ...){
      obj <- fortify(object, axes = axes, ...)
      obj <- obj[obj$Score %in% layers, , drop = FALSE]
      want <- obj$Score %in% c("species", "sites")
      obj[want, , drop = FALSE]
    }
    

    With this we can then generate any plot that we desire, with appropriate mappings rather than layer-individual mappings

    dune.plot.data <- ggvegan_data(dune.dca)
    p <- ggplot(data = dune.dca, aes(x = DCA1, DCA2, colour = Score)) + 
      geom_point() + 
      geom_text(aes(label = Label), nudge_y = 0.3)
    p
    

    Which gives us what I hope is your desired output point+label plot (from code above)