【问题标题】:Apply a vector of filters based on a string (or vector of strings) in dplyr基于 dplyr 中的字符串(或字符串向量)应用过滤器向量
【发布时间】:2020-03-31 04:34:02
【问题描述】:

R 和 tidyverse 有一些非常强大但同样神秘的方法可以将字符串转换为可操作的表达式。我觉得需要成为专家才能真正了解如何使用它们。

注意:这个问题与this one 的不同之处在于我专门询问了一个向量(即多个)过滤条件。我演示了单个过滤器的解决方案,当我尝试多种方法将其扩展到多个过滤器时失败。

我想做一些类似的事情:

df = data.frame(A=1:10, B=1:10)
df %>% filter(A<3, B<5)

但过滤器包含在字符串(例如 "A&lt;3, B&lt;5")或字符向量(例如 c("A&lt;3", "B&lt;5"))中。

我可以的

df %>% filter(eval(str2expression("A<3")))
#   A B
# 1 1 1
# 2 2 2

但这不起作用:

df %>% filter(eval(str2expression("A<3, B<5")))
Error in str2expression("A<3, B<5") : <text>:1:4: unexpected ','
1: A<3,
       ^

这些也不起作用:

> df %>% filter(!!c(str2expression("A<3"), str2expression("B<5")))
Error: Argument 2 filter condition does not evaluate to a logical vector
> df %>% filter(!!!c(str2expression("A<3"), str2expression("B<5")))
Error: Can't splice an object of type `expression` because it is not a vector
Run `rlang::last_error()` to see where the error occurred.

由于某种原因,从str2expression 计算表达式向量只应用最后一个表达式:

> df %>% filter(eval(c(str2expression("A<3"), str2expression("B<5"))))
#   A B
# 1 1 1
# 2 2 2
# 3 3 3
# 4 4 4

使用评估表达式的向量完全失败:

> df %>% filter(!!!c(eval(str2expression("A<3")), eval(str2expression("B<5"))))
Error in eval(str2expression("A<3")) : object 'A' not found

我能做到:

> df %>% filter(!!!c(expr(A<3), expr(B<5)))
#   A B
# 1 1 1
# 2 2 2

这告诉我expr(A&lt;3)str2expression("A&lt;3") 不一样

但这不是从字符串开始的。

怎么办?

【问题讨论】:

  • 我已将我的问题标记为重新打开,因为我的问题特别询问条件向量。 “类似”的问题没有。答案是不同的。此外,我的答案更简单。
  • 在我链接的帖子中,有parse_exprs select_expr &lt;- rlang::parse_exprs( select_str ) 与本文中的其他答案相同

标签: r filter dplyr tidyverse


【解决方案1】:

您可以使用 parse_exprs 中的 rlang

library(dplyr)
expr <- c("A<3", "B<5")

filter(df, !!!rlang::parse_exprs(expr))

#  A B
#1 1 1
#2 2 2

或者你可以结合这两个表达式然后在eval中使用它

filter(df, eval(parse(text = paste0(expr, collapse = "&"))))

#  A B
#1 1 1
#2 2 2

【讨论】:

    【解决方案2】:

    显然,从@Ronak Shah 的回答中学习,在 dplyr 中,我可以在过滤器中使用多个条件和单个 &amp; 而不是逗号。我完全不明白——这与 and 逻辑不是一回事:

    > df %>% filter(A<3 & B<5)
      A B
    1 1 1
    2 2 2
    > df %>% filter(A<3 && B<5)
        A  B
    1   1  1
    2   2  2
    3   3  3
    4   4  4
    5   5  5
    6   6  6
    7   7  7
    8   8  8
    9   9  9
    10 10 10
    

    尽管如此,以下方法确实有效:

    > df %>% filter(eval(str2expression("A<3 & B<5")))
      A B
    1 1 1
    2 2 2
    > df %>% filter(eval(str2expression("A<6 & B<5")))
      A B
    1 1 1
    2 2 2
    3 3 3
    4 4 4
    

    【讨论】:

    猜你喜欢
    • 2018-09-28
    • 1970-01-01
    • 1970-01-01
    • 2018-02-19
    • 1970-01-01
    • 2012-09-05
    • 1970-01-01
    • 2017-12-01
    • 1970-01-01
    相关资源
    最近更新 更多