0

I have a simple ggplot function here that plots biplot arrows from a capscale ordination. I do realize there are builtin vegan packages, and even ggvegan to do this for me. This actually ends up being part of a more complicated other function and I do actually need to get this working for this simple case.

## import packages
library(vegan)
library(ggplot)

## load in some toy data
data(varespec)
data(varechem)

## Basic capscale ordination
vare.cap <- capscale(varespec ~ N + P + K + Condition(Al), varechem,
                     dist="bray")

## Function takes the capscale object and plots out the biplot vectors
myplotcap <- function(cap, choices = c(1,2)){
                                        # Get biplot scores from capscale, turn them into a data frame
    scoresdf <- data.frame(scores(cap, display = c("bp"), choices = choices))
                                        # Add the rownames as their own column
    scoresdf <- mutate(scoresdf, Row.names = rownames(scoresdf))

    p <- ggplot(scoresdf) +
                                        # segments pointing from origin to biplot location
        geom_segment(aes(x = 0, y = 0, xend = CAP1, yend = CAP2)) +
                                        # lables
        geom_text(aes(x = CAP1 * 1.05, y = CAP2 * 1.05, label = Row.names))
    p
}

## Actually plot the function
myplotcap(vare.cap)

What I'd really like to do here, is be able to modify the "choices" so that I can plot CAP1 vs CAP3. Currently if I run

myplotcap(vare.cap, choices = c(1,3))

Error in FUN(X[[i]], ...) : object 'CAP2' not found

R gets confused because it is looking for CAP2 and the scores function object actually renames the second column as CAP3.

I'd like to do something like tell R what objects to look for.

CAPaName <- paste("CAP", choices[1], sep = "")
CAPbName <- paste("CAP", choices[2], sep = "")

And then somehow turn these strings into objects in the function. Something like replacing all instances of CAP1 with as.object(CAPaName), so my function would look like:

myplotcap <- function(cap, choices = c(1,2)){
                                        # Get biplot scores from capscale, turn them into a data frame
    scoresdf <- data.frame(scores(cap, display = c("bp"), choices = choices))
                                        # Add the rownames as their own column
    scoresdf <- mutate(scoresdf, Row.names = rownames(scoresdf))

    p <- ggplot(scoresdf) +
                                        # segments pointing from origin to biplot location
        geom_segment(aes(x = 0, y = 0, xend = as.object(CAPaName), yend = as.object(CAPbName))) +
                                        # lables
        geom_text(aes(x = as.object(CAPaName) * 1.05, y = as.object(CAPbName) * 1.05, label = Row.names))
    p
}

Except using syntax that actually works. Any suggestions here?

ohnoplus
  • 1,205
  • 1
  • 17
  • 29
  • Use `aes_string()` rather than `aes()` to pass column names as strings to ggplot. – MrFlick Oct 02 '17 at 19:16
  • Yep. Totally a duplicate of that first one. Good answer there, replacing `as.object` with `get` in my code above works wonders. – ohnoplus Oct 02 '17 at 20:04
  • That is the least safe way to do that. Better to use aes_string to do the proper mapping to the data frame. – MrFlick Oct 02 '17 at 20:06

0 Answers0