如何在dplyr :: filter中使用变量?

时间:2015-12-11 09:19:01

标签: r dplyr

我有一个与数据框中的列同名的变量:

df <- data.frame(a=c(1,2,3), b=c(4,5,6))
b <- 5

我想获取df$b == b的行,但dplyr将其解释为df$b == df$b

df %>% filter(b == b) # interpreted as df$b == df$b
#   a b
# 1 1 4
# 2 2 5
# 3 3 6

如果我更改变量名称,则可以:

B <- 5
df %>% filter(b == B) # interpreted as df$b == B
#   a b
# 1 2 5

我想知道是否有更好的方法告诉filter b是指外部变量。

3 个答案:

答案 0 :(得分:16)

您可以使用get函数从环境中获取变量的值。

df %>% filter(b == get("b")) # Note the "" around b

答案 1 :(得分:16)

最近我发现这是解决这个问题的一个优雅的解决方案,尽管我只是开始关注它是如何工作的。

df %>% filter(b == UQ(b))

的语法糖

UQ

我对此的高级认识是!!(取消引用)操作会导致在筛选操作之前评估其内容,因此不会在data.frame中对其进行评估。

在{quasi-quotation'下的answer中对此进行了描述。我要注意的是,本文还包括一些与NSE相关的类似问题的解决方案。

对上述内容的一个警告 - 我倾向于将df %>% filter(!!b == b)置于我的表达式的末尾,如上所述。如果你把它放在开头:

df %>% filter(!!(b == b))

然后它将被评估为df %>% filter(5 == 5)

相当于写> quo(filter(df, !!b == b)) <quosure: global> ~filter(df, TRUE)

UQ()

上面的 if (as.numeric(fld 3) > 100) { x <- data.frame(computed fld1, computed fld 2, computed fld3) write.table(x, "outputfile.csv", sep=",",append=TRUE, quote=FALSE, col.names=FALSE, row.names=FALSE) } 选项没有此问题。

答案 2 :(得分:8)

作为一般解决方案,您可以使用filter的SE(标准评估)版本,即filter_。在这种情况下,事情变得有点混乱,因为你正在混合一个变量和一个外部&#39;单个表达式中的常量。以下是使用interp函数执行此操作的方法:

library(lazyeval)
df %>% filter_(interp(~ b == x, x = b))

如果您想在b中使用更多值,可以写:

df %>% filter_(interp(~ b == x, .values = list(x = b)))