【问题标题】:How to filter a dataframe with a character vector如何使用字符向量过滤数据框
【发布时间】:2020-02-26 15:15:57
【问题描述】:

我正在尝试从包dplyr 中过滤带有filter() 函数的data.frame。这里的主要问题是我想对条件使用向量。

例如

library(dplyr)
conditions <- c("Sepal.Width<3.2","Species==setosa")
DATA <- iris %>%
  filter(conditions) #This doesnt work, of course.

有什么功能需要

conditions <- c("Sepal.Width<3.2","Species==setosa")

作为输入并给我

Sepal.Width<3.2 & Species==setosa

作为输出?我想用eval(parse...)sapplypaste0() 来添加&amp;,但不能让它工作。

我们将不胜感激。

【问题讨论】:

    标签: r filter dplyr


    【解决方案1】:

    存在多个问题。首先,您需要为第二个条件引用内部引号:

    conditions <- c("Sepal.Width < 3.2", "Species == 'setosa'")
    

    然后,您需要指定两个条件之间的关联。在这里,我假设一个&amp;。然后就可以使用eval(parse(...))

    iris %>%
     filter(eval(parse(text = paste(conditions, sep = "&"))))
    
       Sepal.Length Sepal.Width Petal.Length Petal.Width Species
    1           5.1         3.5          1.4         0.2  setosa
    2           4.9         3.0          1.4         0.2  setosa
    3           4.7         3.2          1.3         0.2  setosa
    4           4.6         3.1          1.5         0.2  setosa
    5           5.0         3.6          1.4         0.2  setosa
    6           5.4         3.9          1.7         0.4  setosa
    7           4.6         3.4          1.4         0.3  setosa
    8           5.0         3.4          1.5         0.2  setosa
    9           4.4         2.9          1.4         0.2  setosa
    10          4.9         3.1          1.5         0.1  setosa
    

    另一方面,我认为引用@Martin Mächler 来警告与此方法相关的潜在问题总是很重要的:

    (可能)唯一的连接是通过 parse(text = ....) 并且一切正常 R 程序员应该知道这很少是有效或安全的 表示构造表达式(或调用)。而是了解更多关于 替代(),报价(),可能还有使用的力量 do.call(替代,......).

    【讨论】:

    • 感谢您的回答。没有注意到 setosa 中的报价,它对我有用!正如我向@sindri_baldur 询问的那样,您知道没有 Eval(parse) 的其他方法吗?
    【解决方案2】:

    这是一个方式:

    conditions <- c("Sepal.Width<3.2","Species=='setosa'")
    # note the small change here:               ↑      ↑
    DATA <- iris %>%
      filter(eval(parse(text = paste(conditions, collapse = "&"))))
    
    > DATA
       Sepal.Length Sepal.Width Petal.Length Petal.Width Species
    1           4.9         3.0          1.4         0.2  setosa
    2           4.6         3.1          1.5         0.2  setosa
    3           4.4         2.9          1.4         0.2  setosa
    4           4.9         3.1          1.5         0.1  setosa
    5           4.8         3.0          1.4         0.1  setosa
    6           4.3         3.0          1.1         0.1  setosa
    7           5.0         3.0          1.6         0.2  setosa
    8           4.8         3.1          1.6         0.2  setosa
    9           4.9         3.1          1.5         0.2  setosa
    10          4.4         3.0          1.3         0.2  setosa
    11          4.5         2.3          1.3         0.3  setosa
    12          4.8         3.0          1.4         0.3  setosa
    

    【讨论】:

    • 我明白了,我不知道为什么它一开始对我不起作用。谢谢,您知道是否有没有 eval(parse..) 的方法吗?
    • @kowa 我们可能遇到了 XY 问题。你的申请是什么?
    • 我会用to来对数据进行分类,所以我会是唯一一个可以访问代码的人,这就是为什么我不害怕XSS攻击,但不介意更安全。
    【解决方案3】:

    一个整洁的方法是使用rlang::parse_exprs()

    library(dplyr)
    
    conditions <- c("Sepal.Width < 3.2", "Species == 'setosa'")
    
    iris %>%
      filter( !!! rlang::parse_exprs(conditions))
    
       Sepal.Length Sepal.Width Petal.Length Petal.Width Species
    1           4.9         3.0          1.4         0.2  setosa
    2           4.6         3.1          1.5         0.2  setosa
    3           4.4         2.9          1.4         0.2  setosa
    4           4.9         3.1          1.5         0.1  setosa
    5           4.8         3.0          1.4         0.1  setosa
    6           4.3         3.0          1.1         0.1  setosa
    7           5.0         3.0          1.6         0.2  setosa
    8           4.8         3.1          1.6         0.2  setosa
    9           4.9         3.1          1.5         0.2  setosa
    10          4.4         3.0          1.3         0.2  setosa
    11          4.5         2.3          1.3         0.3  setosa
    12          4.8         3.0          1.4         0.3  setosa
    

    【讨论】:

      猜你喜欢
      • 2021-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-30
      • 1970-01-01
      • 2023-03-14
      相关资源
      最近更新 更多