0

I have a function provided to do a PCA plot which is shown below. I want to pass the names of the principal components(variables a and b) but have not figured a way to do this. I have tried using aes_string. Error received is Error in eval(expr, envir, enclos) : object '.names' not found

Per suggestion below, I have put a concrete example. One where the function works and another where it does not. Goal is to pass variables to this function.

 #data
  d = iris[1:4]
  #########################################################################
  # PCA_Plot functions
  #########################################################################

  PCA_Plot = function(pcaData)
  {
    library(ggplot2)

    theta = seq(0,2*pi,length.out = 100)
    circle = data.frame(x = cos(theta), y = sin(theta))
    p = ggplot(circle,aes(x,y)) + geom_path()

    loadings = data.frame(pcaData$rotation, .names = row.names(pcaData$rotation))
    p + geom_text(data=loadings, mapping=aes(x = PC1, y = PC2, label = .names, colour = .names, fontface="bold")) +
      coord_fixed(ratio=1) + labs(x = "PC1", y = "PC2")
  }
  # non-working function with two extra variables
  PCA_Plot2 = function(pcaData, var1, var2)
  {
    library(ggplot2)

    theta = seq(0,2*pi,length.out = 100)
    circle = data.frame(x = cos(theta), y = sin(theta))
    p = ggplot(circle,aes(x,y)) + geom_path()

    loadings = data.frame(pcaData$rotation, .names = row.names(pcaData$rotation))
    p + geom_text(data=loadings, mapping=aes(x = var1, y = var2, label = .names, colour = .names, fontface="bold")) +
      coord_fixed(ratio=1) + labs(x = var1, y = var2)
  }


  #pca
  library(stats)
  p = prcomp(d)

  PCA_Plot(p) #works

  PCA_Plot2(p, "PC1", "PC2") # ERROR Error: Discrete value supplied to 
  continuous scale
2
  • 4
    you should provide a reproducible example. Commented Apr 20, 2018 at 15:57
  • 2
    To further @MLavoie's comment about a reproducible example, if you could provide us with an easy to load into R sample of data, using dput(data) or dput(head(data,50)) it will go a long way in helping us help you. Commented Apr 20, 2018 at 16:12

2 Answers 2

2

You were almost there with aes_string! You are providing var1 and var2 as strings, but not the label aesthetic .names. If you change that to ".names", your function will work.

I altered your function a bit:

  1. Return the ggplot object directly instead of assigning an intermediate variable
  2. Merged the plotting calls
  3. Moved the library call outside of the function (no need to load the library every time you call the function).

    library(stats)
    library(ggplot2)
    
    PCA_Plot2 = function(pcaData, var1, var2)
    {
    
      theta = seq(0,2*pi,length.out = 100)
    
       circle = data.frame(x = cos(theta), y = sin(theta))
    
       loadings = data.frame(pcaData$rotation,  .names = row.names(pcaData$rotation))
    
      ggplot(circle, aes(x,y)) +
        geom_path() +
        geom_text(aes_string(x = var1, y = var2, label = ".names"), inherit.aes = FALSE, data = loadings) +
        coord_fixed(ratio=1) +
        labs(x = var1, y = var2)
    }
    
    PCA_Plot2(p, "PC1", "PC2")
    

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

1

Without having your data, here's a simplified example of your function using some base R datasets. I think you're having a quosure problem: you can't directly access columns just by using the string that corresponds to a column name. Instead, you want to use something like q_var <- quo(var), and then !!q_var in referring to the column by its bare name. I have a fair amount of trouble with writing functions like this, but see the "Programming with dplyr" vignette for more explanation.

library(tidyverse)

make_plot <- function(full_df, var1, var2) {
    # use quo to access the values in the strings var1, var2
    quo_var1 <- quo(var1)
    quo_var2 <- quo(var2)

    df <- full_df %>% rownames_to_column("name") %>% select(name, x = !!quo_var1, y = !!quo_var2)

    ggplot(df, aes(x = x, y = y)) +
        geom_text(aes(label = name), size = 2.5) +
        # still have var1, var2 strings--can use as labels
        labs(x = var1, y = var2)
}

make_plot(mtcars, "mpg", "disp")

make_plot(mtcars, "hp", "qsec")

make_plot(as.data.frame(state.x77), "Income", "Life Exp")

Created on 2018-04-20 by the reprex package (v0.2.0).

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.