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

问题描述 投票:0回答:5

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

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
指的是外部变量。

r dplyr
5个回答
55
投票

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

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

这是

的语法糖

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

这种情况的高级意义是,

UQ
(取消引用)操作会导致其内容在过滤操作之前被评估,因此不会在 data.frame 内评估它。

这在 Advanced R章节中关于“准引用”进行了描述。本章还包括一些与非标准评估(NSE)相关的类似问题的解决方案。


20
投票

您可以使用

get
函数从环境中获取变量的值。

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

10
投票

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

来自文档:

注意.data只是一个代词,它不是真正的数据框。这意味着您无法获取其名称或在 .data 的内容上映射函数。同样,.env 也不是实际的 R 环境。

您不一定需要在此处使用

.data$b
,因为评估会在数据框中搜索具有该名称 first 的列(正如您所发现的)。


8
投票

作为通用解决方案,您可以使用

filter
的SE(标准评估)版本,即
filter_
。在这种情况下,事情会变得有点混乱,因为您在单个表达式中混合了变量和“外部”常量。以下是使用
interp
函数执行此操作的方法:

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

如果您想在

b
中使用更多值,您可以写:

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

0
投票

对于那些对如何使用列作为变量感兴趣的人,我发现这个解决方案是最快且易于理解的:

df %>% filter(!!as.name(column_name) == !!b)
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.