【问题标题】:Scoped filtering over column range with & logic使用 & 逻辑对列范围进行范围过滤
【发布时间】:2019-02-01 13:18:01
【问题描述】:

我正在尝试找到一种过滤数据框中特定列范围的方法,以过滤到包含该列范围内某处某个字符向量的所有元素的行。

例如,如果我的列范围如下:

library(dplyr)

set.seed(10)

df <- tibble(
  a = sample(LETTERS[1:10], 10),
  b = sample(LETTERS[1:10], 10),
  c = sample(LETTERS[1:10], 10),
  d = sample(LETTERS[1:10], 10),
  e = sample(LETTERS[1:10], 10)
)

df
#> # A tibble: 10 x 5
#>    a     b     c     d     e    
#>    <chr> <chr> <chr> <chr> <chr>
#>  1 F     G     I     F     C    
#>  2 C     F     F     A     J    
#>  3 D     A     G     B     A    
#>  4 E     E     C     G     F    
#>  5 A     C     H     C     B    
#>  6 B     I     D     D     H    
#>  7 G     H     E     E     E    
#>  8 J     D     A     J     G    
#>  9 H     J     B     H     D    
#> 10 I     B     J     I     I

我想过滤出至少有一个 "A" 实例的行和至少有一个 "C" 实例我可以使用 filter_at 两次来获得所需的结果:

df %>% 
  filter_at(vars(a:e), any_vars(. == "A")) %>% 
  filter_at(vars(a:e), any_vars(. == "C"))
#> # A tibble: 2 x 5
#>   a     b     c     d     e    
#>   <chr> <chr> <chr> <chr> <chr>
#> 1 C     F     F     A     J    
#> 2 A     C     H     C     B

但是,我正在尝试以闪亮的方式实现这一点,其中过滤条件作为来自选择输入的向量c("A", "C"),那么有没有一种方法可以通过使用向量的单个过滤函数来做到这一点?

使用%in% 将不起作用,因为它返回任何带有"A" 的行或 "C"

df %>% 
  filter_at(vars(a:e), any_vars(. %in% c("A", "C")))
#> # A tibble: 6 x 5
#>   a     b     c     d     e    
#>   <chr> <chr> <chr> <chr> <chr>
#> 1 F     G     I     F     C    
#> 2 C     F     F     A     J    
#> 3 D     A     G     B     A    
#> 4 E     E     C     G     F    
#> 5 A     C     H     C     B    
#> 6 J     D     A     J     G

谢谢!

【问题讨论】:

    标签: r dplyr tidyverse


    【解决方案1】:

    您可以在循环内过滤:

    filter_vec <- c("A", "C")
    
    df_filtered <- df
    for (f in filter_vec) {
      df_filtered <- filter_at(df_filtered,
                               vars(a:e),
                               any_vars(. == f))
    }
    
    df_filtered
    #> # A tibble: 2 x 5
    #>   a     b     c     d     e    
    #>   <chr> <chr> <chr> <chr> <chr>
    #> 1 C     F     F     A     J    
    #> 2 A     C     H     C     B    
    

    【讨论】:

      【解决方案2】:

      完全tidyverse 解决方案,虽然as_data_frame 和$ 调用看起来很丑,嵌套函数也不理想,但它们都是在管道内处理的,没有循环。

      target = c('A', 'C')
      
      flag = df %>% 
        select(a:e) %>%  # If you have other columns, this does the same scoping
        rowwise %>% 
        do(as_data_frame(all(target %in% .))) %>% 
        .$value
      
      df %>% filter(flag)
      #> # A tibble: 2 x 5
      #>   a     b     c     d     e    
      #>   <chr> <chr> <chr> <chr> <chr>
      #> 1 C     F     F     A     J    
      #> 2 A     C     H     C     B
      

      由reprex package (v0.2.1) 于 2019 年 2 月 1 日创建

      我很久以前就记得 rowwise 调用对于非常长的 data.frames 来说非常慢,但那是特定于您的应用程序的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-02-02
        • 1970-01-01
        • 2018-05-13
        • 1970-01-01
        • 2014-02-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多