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


105

我有一个ggplot命令

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

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

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 )

Answers:


161

您可以使用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...论点,因此无论如何都不需要。(此问题中的问题
smci

3
只需添加注释以使人们了解ggplot2版本3.0.0的更新即可了解Moody_Mudskipper的答案
Gregor Thomas

@buncis这不是真的,引用"column_name""column"不会工作
大卫·罗宾逊

@DavidRobinson对不起我的错误,我看不到代码包装在带有参数的函数上,会删除我的注释
Buncis

“麻烦”?具有讽刺意味的是,R中的非标准评估是我在编程语言中遇到的最繁琐的“功能”。真是疯了。
jessexknight

43

发行说明ggplot2 V3.0.0

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()
}

它将使用名称aka符号和字符串文字

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

正如莱昂内尔所说ensym()

它的意思是模仿可以在LHS中提供两个参数的语法,例如list(bare = 1,“ quoted” = 2)


关于的注释 enquo()

enquo()用引号引起来的表达式(不一定是符号),它不会像这样将字符串文字转换为符号,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)

12
这种tidyeval的东西太烦人了。aes()本身的文档enquo()只是在讨论,但没有用。谁曾听说过ensym()?BIG SIGH
CoderGuy123

@Moody_Mudskipper对于f2,所有四个示例均有效,捕获变量(即aname <- "mjr"; f2(aname))中的列名称也有效。如果我添加代码来使用dplyr它来操纵数据框,则尝试使用变量名而不是变量名中的字符串查找列。换句话说,我如何rates.by.groups %>% group_by(!!column)...开始工作并仍然支持这三种呼叫方式f2
Steveb

1
“捕获变量中的列名也是如此”:它不会失败,但不会返回相同的结果,ensym旨在处理作为名称提供的参数,并允许使用引号引起来。我相信您希望将参数视为一个名称,如果找不到该名称,则使用该值。这实际上是用发生的select,但不是用group_by... 发生的。可以破解它,但并不明显。如果这对您很重要,我认为这应该得到自己的问题。
Moody_Mudskipper

@Moody_Mudskipper谢谢。我同时使用了两者selectgroup_by因此可能是问题所在。我可以创建一个新问题,但是我需要拿出一个简单的示例并检查是否已回答。如果没有,我可以发布。
Steveb

如何使用 !!如果是facet_grid?它可以使用,facet_grid(cols = vars(!!column))但会引发错误facet_grid(~ !!column)
mRiddle

14

尝试使用aes_string代替aes


5
这是很好的建议,但是您能告诉他们为什么吗?aes_string使您对非变量使用“”,而对变量使用无引号。aes_string(x =“ foo”,y =“ fee”,group = variable)
mtelesha

@mtelesha可能是因为变量具有字符串作为其值
Buncis

9

另一个选择(ggplot2 > 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软件包(v0.2.1.9000)创建于2019-04-04


0

使用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-使用自定义函数的错误栏


0

这是一个非常简单的示例。

做两件事

  1. 将字符串变成符号
  2. !!使用时添加
select_col <- sym("Petal.Length")

iris %>% 
  ggplot(aes(x = Sepal.Length, y = !!select_col)) +
  geom_point()
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.