我有一个数据框,想要以两种方式之一过滤它,通过列"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
Run Code Online (Sandbox Code Playgroud)
但是说我想使用变量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
Run Code Online (Sandbox Code Playgroud)
如何将值column转换为列名?
Sal*_*m B 32
从当前的dplyr帮助文件(由我强调):
dplyr曾经提供每个动词的双重版本,后缀为下划线.这些版本具有标准评估(SE)语义:它们不是通过代码(如NSE动词)接受参数,而是通过值来获取参数.他们的目的是使用dplyr进行编程成为可能.但是,dplyr现在使用整洁的评估语义.NSE动词仍然捕获它们的参数,但您现在可以取消引用这些参数的一部分.这提供了NSE动词的完全可编程性.因此,强调版本现在是多余的.
在使用dplyr编程的插图中可以学到什么不相称的确切含义.它是通过函数或语法糖来实现的.现在有一些情况 - 比如你的情况 - 只有前者才能正常工作,因为它可以与单身相撞."this"columndplyr::filter()column
适用于您的示例:
library(dplyr)
df <- data.frame(this = c(1, 2, 2),
that = c(1, 1, 2))
column <- "this"
df %>% filter(UQ(as.symbol(column)) == 1)
# this that
# 1 1 1
Run Code Online (Sandbox Code Playgroud)
但不是:
df %>% filter(!!as.symbol(column) == 1)
# [1] this that
# <0 Zeilen> (oder row.names mit Länge 0)
Run Code Online (Sandbox Code Playgroud)
symbol如果你要么添加一些额外的圆括号(感谢Martijn vd Voort的建议),语法糖会再次起作用:
df %>% filter((!!as.symbol(column)) == 1)
# this that
# 1 1 1
Run Code Online (Sandbox Code Playgroud)
或者,如果您只是交换两个比较操作数(感谢提示的carand):
df %>% filter(1 == !!as.symbol(column))
# this that
# 1 1 1
Run Code Online (Sandbox Code Playgroud)
Ric*_*ven 24
我会避免get()一起使用.在这种情况下,这似乎很危险,特别是如果你正在编程的话.您可以使用未评估的调用或粘贴的字符串,但您需要使用filter_()而不是filter().
df <- data.frame(this = c(1, 2, 2), that = c(1, 1, 2))
column <- "this"
Run Code Online (Sandbox Code Playgroud)
选项1 - 使用未评估的电话:
你可以硬编码y的1,但在这里我告诉它y来说明如何您可以轻松地更改表达式的值.
expr <- lazyeval::interp(quote(x == y), x = as.name(column), y = 1)
## or
## expr <- substitute(x == y, list(x = as.name(column), y = 1))
df %>% filter_(expr)
# this that
# 1 1 1
Run Code Online (Sandbox Code Playgroud)
选项2 - 使用paste()(并且显然更容易):
df %>% filter_(paste(column, "==", 1))
# this that
# 1 1 1
Run Code Online (Sandbox Code Playgroud)
这两个选项的主要内容是我们需要使用filter_()而不是filter().事实上,根据我的阅读,如果你正在编程,dplyr你应该总是使用这些*_()功能.
我使用这篇文章作为一个有用的参考:字符串作为函数参数r,我使用的是dplyr版本0.3.0.2.
这是最新 dplyr 版本的另一个解决方案:
df <- data.frame(this = c(1, 2, 2),
that = c(1, 1, 2))
column <- "this"
df %>% filter(.[[column]] == 1)
# this that
#1 1 1
Run Code Online (Sandbox Code Playgroud)
关于理查德的解决方案,只想添加一下,如果你的列是字符.您可以添加shQuote按字符值过滤.
例如,您可以使用
df %>% filter_(paste(column, "==", shQuote("a")))
Run Code Online (Sandbox Code Playgroud)
如果你有多个过滤器,你可以指定collapse = "&"在paste.
df %>$ filter_(paste(c("column1","column2"), "==", shQuote(c("a","b")), collapse = "&"))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
20538 次 |
| 最近记录: |