我有一个数据框,想用两种方式之一过滤它,列“this”或列“that”。我希望能够引用列名作为变量。如何(在dplyr
中,如果有区别的话)通过变量引用列名?
library(dplyr)
df <- data.frame(this = c(1, 2, 2), that = c(1, 1, 2))
df
# this that
# 1 1 1
# 2 2 1
# 3 2 2
df %>% filter(this == 1)
# this that
# 1 1 1
但是假设我想使用变量column
来保存“this”或“that”,并过滤column
的值,as.symbol
和get
在其他上下文中都可以工作,但在下面的上下文中不行:
column <- "this"
df %>% filter(as.symbol(column) == 1)
# [1] this that
# <0 rows> (or 0-length row.names)
df %>% filter(get(column) == 1)
# Error in get("this") : object 'this' not found
如何将column
的值转换为列名?
8条答案
按热度按时间bybem2ql1#
使用rlang的injection范例
从current dplyr documentation(我着重强调):
dplyr曾经提供两个版本的后缀为下划线的动词,这两个版本有标准求值(SE)语义:它们不像NSE动词那样通过代码获取参数,而是通过值获取参数。它们的目的是使dplyr编程成为可能。然而,dplyr现在使用了整洁的求值语义。NSE动词仍然捕获它们的参数,但是**你现在可以取消引用这些参数的一部分。这为NSE动词提供了完全的可编程性。**因此,下划线的版本现在是多余的。
因此,本质上我们需要执行两个步骤才能在
dplyr::filter()
中引用变量column
的值"this"
:1.我们需要将字符类型的变量
column
转换为symbol
类型。使用基数R,这可以通过
as.name()
的别名as.symbol()
函数来实现,前者是tidyverse开发人员的首选,因为它采用更现代的术语(R型而不是S模式)。
或者,通过tidyverse的
rlang::sym()
也可以实现相同的效果。1.我们需要将1)中的符号注入
dplyr::filter()
表达式。这是通过所谓的injection operator**
!!
**来完成的,它基本上是syntactic sugar,允许在R计算代码之前修改它。(In
dplyr
的早期版本(或相应的底层rlang
)曾经存在!!
与单个!
冲突的情况(包括您的情况),但这不再是问题,因为!!
获得了正确的操作符优先级。)应用于您的示例:
使用替代解决方案
在
dplyr::filter()
* 中引用变量column
的值"this"
的其他方法不依赖于rlang的注入范例 *,包括:dplyr::if_any()
/dplyr::if_all()
与tidyselect::all_of()
.data
pronoun和base R's[[
:.
参数占位符和base R's[[
:tzcvj98z2#
我会避免同时使用
get()
。在这种情况下似乎会相当危险,特别是在编程时。您可以使用未求值的调用或粘贴的字符串,但您需要使用filter_()
而不是filter()
。选项1-使用未评估的调用:
您可以将
y
硬编码为1
,但这里我将其显示为y
,以说明如何轻松地更改表达式值。选项2-使用
paste()
(显然更容易):这两个选项的主要问题是我们需要使用
filter_()
而不是filter()
,事实上,从我所读到的,如果你用dplyr
编程,你应该总是使用*_()
函数。我把这篇文章作为一个有用的参考:character string as function argument r,我使用的是
dplyr
版本0.3.0.2。rjzwgtxy3#
下面是dplyr最新版本的另一个解决方案:
2mbi3lxu4#
关于Richard的解决方案,我只想补充一点,如果你的列是字符型的,你可以添加
shQuote
来过滤字符值。例如,您可以使用
如果有多个过滤器,则可以在
paste
中指定collapse = "&"
。ttp71kqs5#
最新的方法是使用
my.data.frame %>% filter(.data[[myName]] == 1)
,其中myName
是包含列名的环境变量。u4vypkhs6#
或者使用
filter_at
cclgggtu7#
像萨利姆B上面解释,但有一个小的变化:
即,只是颠倒条件,因为
!!
否则表现为ej83mcc08#
可以使用across(all_of())语法,它将字符串作为参数