首页 文章

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

提问于
浏览
16

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

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 回答

  • 15

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

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

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

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

    这是语法糖

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

    我的高级意义是 UQ (取消引用)操作导致其内容在过滤操作之前被评估,因此它不在data.frame中进行评估 .

    这在article中描述,在'quasi-quotation'下 . 我要注意的是,本文还包括一些与NSE相关的类似问题的解决方案 .

    对上面的一个警告 - 我倾向于将 !! 置于我的表达式的末尾,如上所述 . 如果你把它放在开头:

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

    那么它将被评估为 df %>% filter(!!(b == b))

    这相当于写 df %>% filter(5 == 5)

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

    上面的 UQ() 选项没有这个问题 .

  • 8

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

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

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

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

相关问题