我有一个与数据框中的列同名的变量:
df <- data.frame(a=c(1,2,3), b=c(4,5,6))
b <- 5
Run Code Online (Sandbox Code Playgroud)
我想把行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
Run Code Online (Sandbox Code Playgroud)
如果我更改变量名称,它可以工作:
B <- 5
df %>% filter(b == B) # interpreted as df$b == B
# a b
# 1 2 5
Run Code Online (Sandbox Code Playgroud)
我想知道是否有更好的方法来filter
指出b
外部变量.
小智 20
最近我发现这是解决这个问题的一个优雅的解决方案,尽管我只是开始关注它是如何工作的.
df %>% filter(b == !!b)
这是语法糖
df %>% filter(b == UQ(b))
我对此的高级认识是UQ
(un-quote)操作导致在筛选操作之前评估其内容,因此不在data.frame中对其进行求值.
本文在"准引用"下对此进行了描述.我要注意的是,本文还包括一些与NSE相关的类似问题的解决方案.
对上述内容的一个警告 - 我倾向于将!!
表达式的结尾放在上面.如果你把它放在开头:
df %>% filter(!!b == b)
那么它将被评估为 df %>% filter(!!(b == b))
这相当于写作df %>% filter(5 == 5)
:
> quo(filter(df, !!b == b))
<quosure: global>
~filter(df, TRUE)
Run Code Online (Sandbox Code Playgroud)
UQ()
上面的选项没有这个问题.
nis*_*ist 13
您可以使用该get
函数从环境中获取变量的值.
df %>% filter(b == get("b")) # Note the "" around b
Run Code Online (Sandbox Code Playgroud)
rlang
,它是用 , 导入的dplyr
,具有.env
和.data
代词,正好适合这种情况,因为数据屏蔽而需要明确。要显式引用数据框中的列,.data
请使用并显式引用您的环境使用.env
:
library(dplyr)
df %>%
filter(.data$b == .env$b) # b == .env$b works the same here
a b
1 2 5
Run Code Online (Sandbox Code Playgroud)
从文档中:
请注意,.data 只是一个代词,它不是真正的数据框。这意味着您无法获取其名称或在 .data 的内容上映射函数。同样,.env 也不是实际的 R 环境。
您不一定需要在此处使用,因为评估首先.data$b
在数据框中搜索具有该名称的列(正如您所发现的)。
作为一般解决方案,您可以使用SE(标准评估)版本filter
,即filter_
.在这种情况下,事情变得有点混乱,因为你在一个表达式中混合了一个变量和一个"外部"常量.以下是使用该interp
功能的方法:
library(lazyeval)
df %>% filter_(interp(~ b == x, x = b))
Run Code Online (Sandbox Code Playgroud)
如果您想使用更多值,b
可以写:
df %>% filter_(interp(~ b == x, .values = list(x = b)))
Run Code Online (Sandbox Code Playgroud)