我在一个以data.frame dplyr
为参数的函数中使用df
。
在某些时候,我想基于我刚刚创建的名为n
的向量进行过滤。但是,如果n
也是输入data.frame中变量的名称,那么这将无法工作。
library(dplyr)
df <- data.frame(n = c(0L, 0L))
n <- c(1L, 1L)
filter(df, n == 1L)
#> [1] n
#> <0 rows> (or 0-length row.names)
由于该函数适用于任何数据帧,我想避免这种情况。我尝试使用与全局环境关联的公式/惰性对象,但这返回了相同的结果:
a <- ~ n == 1L
filter_(df, a)
#> [1] n
#> <0 rows> (or 0-length row.names)
a <- lazy(n == 1L)
filter_(df, a)
#> [1] n
#> <0 rows> (or 0-length row.names)
有优雅的方式吗?
答案 0 :(得分:4)
因为n
既是变量名也是包含值的对象,使用 lazyeval 中的interp
并使用n
作为值(而不是变量)似乎做你想做的事。
library(lazyeval)
filter_(df, interp(~n == 1L, n = n))
n
1 0
2 0
我首先尝试了更复杂的
filter_(df, interp(~n == 1L, .values = list(n = n)))
但更简单的版本似乎也是一样的。
答案 1 :(得分:1)
所有先前的答案都已过时,因为dplyr
现在支持rlang
的引用和取消引用语义。
您可以简单地使用!! n
来防止引用n
(并解释为n
列)。
library(dplyr)
df <- data.frame(n = c(0L, 0L))
n <- c(1L, 1L)
filter(df, !! n == 1L)
## n
## 1 0
## 2 0
另一个使用经典mtcars
的示例:
gear <- 5
# gear == gear is true for all rows!
# this returns the whole dataset
filter(mtcars, gear == gear)
# this works as intended
filter(mtcars, gear == !! gear)
## mpg cyl disp hp drat wt qsec vs am gear carb
## 1 26.0 4 120.3 91 4.43 2.140 16.7 0 1 5 2
## 2 30.4 4 95.1 113 3.77 1.513 16.9 1 1 5 2
## 3 15.8 8 351.0 264 4.22 3.170 14.5 0 1 5 4
## 4 19.7 6 145.0 175 3.62 2.770 15.5 0 1 5 6
## 5 15.0 8 301.0 335 3.54 3.570 14.6 0 1 5 8
答案 2 :(得分:0)
正如你所说,使用NSE和filter_
可能有办法做到这一点,但不知道如何做。我希望像df %>% filter_(n == 1L)
这样的东西可以工作 - 它确实使用了正确的n
,但它只使用了向量的第一个条目。这个替代方案怎么样
df %>% `[`(n == 1L, ,drop = F)
# n
#1 0
#2 0