如何使用变量在ggplot中指定列名

Posted

技术标签:

【中文标题】如何使用变量在ggplot中指定列名【英文标题】:How to use a variable to specify column name in ggplot 【发布时间】:2014-04-14 02:16:01 【问题描述】:

我有一个 ggplot 命令

ggplot( rates.by.groups, aes(x=name, y=rate, colour=majr, group=majr) )

在函数内部。但我希望能够使用函数的参数来挑选出用作颜色和组的列。 IE。我想要这样的东西

f <- function( column ) 
    ...
    ggplot( rates.by.groups, aes(x=name, y=rate, colour= ??? , group=??? ) )

这样ggplot中使用的列是由参数决定的。例如。对于 f("majr") 我们得到的效果是

ggplot( rates.by.groups, aes(x=name, y=rate, colour=majr, group=majr) )

但是对于 f("gender") 我们得到的效果是

  ggplot( rates.by.groups, aes(x=name, y=rate, colour=gender, group=gender) )

我尝试过的一些事情:

ggplot( rates.by.groups, aes(x=name, y=rate, colour= columnName , group=columnName ) )

没用。也没有

e <- environment() 
ggplot( rates.by.groups, aes(x=name, y=rate, colour= columnName , group=columnName ), environment=e )

【问题讨论】:

【参考方案1】:

你可以使用aes_string:

f <- function( column ) 
    ...
    ggplot( rates.by.groups, aes_string(x="name", y="rate", colour= column,
                                        group=column ) )

只要将列作为字符串传递给函数(f("majr") 而不是f(majr))。另请注意,我们将其他列 "name""rate" 更改为字符串。

如果出于某种原因您不想使用aes_string,您可以将其更改为(更麻烦一些):

    ggplot( rates.by.groups, aes(x=name, y=rate, colour= get(column),
                                        group=get(column) ) )

【讨论】:

值得一提的是你不应该/不能做aes_string(x = rates.by.groups$name...,无论如何你不需要因为你已经通过了ggplot(data = rates.by.groups... 参数。 (this question的问题) 只需添加一条注释,将人们指向 Moody_Mudskipper 的答案,其中包含 ggplot2 版本 3.0.0 的更新 @buncis 这不是真的,引用 "column_name""column" 不起作用 @DavidRobinson 对不起我的错误,我没有看到代码被包装在一个带参数的函数上,要删除我的评论 “繁琐”?具有讽刺意味的是,R 中的非标准评估是我在编程语言中遇到过的最麻烦的“功能”。真让人抓狂。【参考方案2】:

来自ggplot2 V3.0.0的release notes:

aes() 现在支持准引用,因此您可以使用 !!、!!! 和 :=。这取代了现在的 aes_() 和 aes_string() 软弃用(但会保留很长时间)。

现在惯用的方法是使用sym()(与基本别名as.name() / as.symbol() 几乎相同)将变量包含的字符串转换为符号,然后使用!! 取消引用它

我们可以模拟 OP 的数据:

library(tidyverse)
rates.by.groups <- data.frame(
  name = LETTERS[1:3],
  rate = 1:3,
  mjr = LETTERS[c(4,4,5)],
  gender = c("M","F","F")
)

f <- function(column) 
  column <- sym(column)
  ggplot(rates.by.groups, 
         aes(x = name, 
             y = rate, 
             fill  = !!column, 
             group = !!column)) +
    geom_col()


f("gender")
f("mjr")
x <- "gender"
f(x)

如果我们宁愿为函数提供原始名称,我们可以这样做:

f2 <- function(column) 
  column <- ensym(column)
  ggplot(rates.by.groups, 
         aes(x = name, 
             y = rate, 
             fill  = !!column, 
             group = !!column)) +
    geom_col()

它适用于名称a.k.a.符号和字符串文字

f2(gender)
f2(mjr)
f2("gender")
f2("mjr")

正如莱昂内尔所说的ensym()

它是为了模仿参数的语法,你可以同时提供 在 LHS 中,例如列表(裸= 1,“引用”= 2)


关于enquo()的注释

enquo()quotes 提供给参数的表达式(不一定是符号),它不会像 ensym() 那样将字符串文字转换为符号,所以它在这里可能不太适应,但我们可以这样做:

f3 <- function(column) 
  column <- enquo(column)
  ggplot(rates.by.groups, 
         aes(x = name, 
             y = rate, 
             fill  = !!column, 
             group = !!column)) +
    geom_col()


f3(gender)
f2(mjr)

【讨论】:

这个 tidyeval 东西太烦人了。 aes() 的文档本身谈到了 enquo(),但它不起作用。谁听说过ensym()?大叹 @Moody_Mudskipper 对于f2,所有四个示例都有效,在变量中捕获列名(即aname &lt;- "mjr"; f2(aname))也是如此。如果我添加代码以使用dplyr 操作数据框,它会尝试使用变量名而不是变量名中的字符串来查找列。换句话说,我如何让rates.by.groups %&gt;% group_by(!!column)...工作并且仍然支持f2的三种调用方式? "在变量中捕获列名也是如此":它不会失败,但不会返回相同的结果,ensym 旨在处理作为名称提供的参数,并容忍他们周围的报价。我相信您希望将参数视为名称,并在找不到名称时回退到该值。这实际上是select 所发生的情况,但group_by 却不是……可以绕过它但并不明显。如果它对你很重要,我认为它应该有自己的问题。 @Moody_Mudskipper 谢谢。我同时使用了selectgroup_by,所以这很可能是问题所在。我可以创建一个新问题,但我需要提出一个简单的示例并检查它是否已被回答。如果没有,我可以发布它。 如何使用!!如果是facet_grid?它适用于facet_grid(cols = vars(!!column)),但会引发facet_grid(~ !!column)的错误【参考方案3】:

另一种选择 (ggplot2 &gt; 3.0.0) 是使用整洁的评估代词 .datarates.by.groups 数据帧中分割所选变量/列。

library(ggplot2)
theme_set(theme_classic(base_size = 14))

# created by @Moody_Mudskipper
rates.by.groups <- data.frame(
  name = LETTERS[1:3],
  rate = 1:3,
  mjr = LETTERS[c(4, 4, 5)],
  gender = c("M", "F", "F")
)

f1 <- function(df, column) 
  gg <- ggplot(df, 
         aes(x = name, 
             y = rate, 
             fill  = .data[[column]], 
             group = .data[[column]])) +
    geom_col() +
    labs(fill = column)
  return(gg)


plot_list <- lapply(list("gender", "mjr"), function(x) f1(rates.by.groups, x) )
plot_list
#> [[1]]

#> 
#> [[2]]

# combine all plots
library(egg)
ggarrange(plots = plot_list,
          nrow = 2,
          labels = c('A)', 'B)'))

由reprex package (v0.2.1.9000) 于 2019 年 4 月 4 日创建

【讨论】:

.data[[ ]] 方法最好的一点是它的通用性。谢谢。 我相信这是自引入 rlang 0.4.* 以来的规范解决方案。这也是 ggplot2 官方小插曲中提出的方式:ggplot2.tidyverse.org/articles/ggplot2-in-packages.html【参考方案4】:

尝试使用aes_string 而不是aes

【讨论】:

这是一个很好的建议,但你能告诉他们为什么吗? aes_string 让你使用 "" 作为非变量,你使用变量 unquotes。 aes_string(x = "foo", y = "fee", group = 变量) @mtelesha 可能是因为变量的值是字符串【参考方案5】:

做这两件事

    将列名转换为符号sym() 当你想使用它时,在符号前面加上!!

示例

my_col <- sym("Petal.Length")

iris %>% 
  ggplot(aes(x = Sepal.Length, y = !!my_col)) +
  geom_point()

【讨论】:

【参考方案6】:

使用aes_string 确实可以解决此问题,但在添加错误栏geom_errorbar 时确实会遇到问题。下面是一个简单的解决方案。

#Identify your variables using the names of your columns indie your dataset
 xaxis   <- "Independent"   
 yaxis   <- "Dependent"
 sd      <- "error"

#Specify error bar range (in 'a-b' not 'a'-'b')
 range   <- c(yaxis, sd)                                #using c(X, y) allows use of quotation marks inside formula
 yerrbar <- aes_string(ymin=paste(range, collapse='-'), 
                       ymax=paste(range, collapse='+'))


#Build the plot
  ggplot(data=Dataset, aes_string(x=xaxis, y=yaxis)) +
    geom_errorbar(mapping=yerrbar, width=15, colour="#73777a", size = 0.5) +
    geom_point   (shape=21)

另外,您还可以使用 ggplot 中的这些行向绘图中添加构面:

facet_grid(formula(paste(Variable1, "~", Variable2)))

这个脚本是根据这个原始帖子修改的:ggplot2 - Error bars using a custom function

【讨论】:

以上是关于如何使用变量在ggplot中指定列名的主要内容,如果未能解决你的问题,请参考以下文章

Fluent NHibernate:如何使用约定在组件中指定列名以供参考?

如何在 SQL Server 的交叉应用联接中指定列名

在ggplot2中指定颜色,轴线和背景的删除

如何在使用变量的动态查询中指定 IN 子句?

如何使用 AWS CloudFormation 在 AWS API Gateway 集成中指定阶段变量?

在 Liquibase 中指定不同的“TAG”列名