【问题标题】:Passing variables to a function using ggplot in r在 r 中使用 ggplot 将变量传递给函数
【发布时间】:2018-04-20 15:39:01
【问题描述】:

我提供了一个函数来绘制如下所示的 PCA 图。我想传递主要组件的名称(变量 a 和 b),但还没有想办法做到这一点。我尝试过使用 aes_string。收到的错误是 eval(expr, envir, enclos) 中的错误:找不到对象 '.names'

根据下面的建议,我举了一个具体的例子。一个功能起作用的地方,另一个不起作用的地方。目标是将变量传递给这个函数。

 #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

【问题讨论】:

  • 你应该提供一个可重现的例子。
  • 为了进一步@MLavoie 对可重现示例的评论,如果您可以使用dput(data)dput(head(data,50)) 为我们提供易于加载到data 的R 示例,它将有很长的路要走帮助我们帮助您。

标签: r ggplot2


【解决方案1】:

你和aes_string 差不多了!您提供var1var2 作为字符串,但不是label 美学.names。如果你把它改成".names",你的函数就可以工作了。

我稍微改变了你的功能:

  1. 直接返回ggplot对象,而不是分配中间变量
  2. 合并绘图调用
  3. 将库调用移到函数之外(每次调用函数时都无需加载库)。

    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")
    

【讨论】:

    【解决方案2】:

    在没有您的数据的情况下,这里有一个使用一些基本 R 数据集的函数的简化示例。我认为您遇到了一个问题:您不能仅通过使用与列名对应的字符串来直接访问列。相反,您想使用q_var <- quo(var) 之类的东西,然后使用!!q_var 来通过其裸名引用列。我在编写这样的函数时遇到了很多麻烦,但请参阅“使用 dplyr 编程”小插图以获得更多解释。

    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")
    

    reprex package (v0.2.0) 于 2018 年 4 月 20 日创建。

    【讨论】:

      猜你喜欢
      • 2018-08-05
      • 2011-02-26
      • 2013-10-08
      • 1970-01-01
      • 2018-11-09
      • 1970-01-01
      • 1970-01-01
      • 2019-06-02
      • 1970-01-01
      相关资源
      最近更新 更多