【问题标题】:filtering based on three columns with dplyr使用 dplyr 基于三列进行过滤
【发布时间】:2020-09-18 12:36:06
【问题描述】:

我有一个看起来像这样的数据框(但有更多的列,并且没有有用的“KEEP”列):

df <- tribble( ~Lots.of.cols, ~analyte, ~meta, ~value, ~KEEP,
     1, "A", "analyte", NA, FALSE,
     1, "A", "unit", "m", FALSE,
     1, "A", "method", NA, FALSE,
     1, "B", "analyte", "4", TRUE,
     1, "B", "unit", "kg", TRUE,
     1, "B", "method", "xxx", TRUE)

我想要做的是过滤掉特定分析物的所有行,如果 meta 是“分析物”的行,值列也是 NA。所以在上面的 df 中,前三行应该被过滤掉,因为第一行有 meta = "analyte" 和 value = NA。最后三行 (analyte = "B") 应保留,因为第四行 (meta = "analyte") 有!is.na(value)

所以我尝试了两种方法。首先是group_by(analyte),然后尝试过滤或替代

df %>% 
  anti_join(.[is.na(.$value) & .$meta == "analyte", ], 
            by = c("Lots.of.cols", "analyte", "meta")) -> df

通过这两种方法,我可以删除 meta = "analyte" &amp; is.na(value) 所在的单个行,但不能删除组中的其他行。

【问题讨论】:

    标签: r dataframe dplyr


    【解决方案1】:

    问题在于您的表格格式不整齐,即 1 个观察值 = 1 行。

    要获得整洁的数据,您需要更广泛地旋转。这就是我旋转、过滤然后重新旋转的原因。

    另外,令人困惑的是,您有两个名为“分析物”的东西不是同一个东西,因此我更改了名称。

    df %>%
        mutate(meta = str_replace(meta, "analyte", "analyte_value")) %>%
        pivot_wider(names_from = meta, values_from = value) %>%
        filter(!is.na(analyte_value)) %>%
        pivot_longer(cols = analyte_value:method)
    #> # A tibble: 3 x 4
    #>   Lots.of.cols analyte name          value
    #>          <dbl> <chr>   <chr>         <chr>
    #> 1            1 B       analyte_value 4    
    #> 2            1 B       unit          kg   
    #> 3            1 B       method        xxx
    

    【讨论】:

    • 当我看到旋转时,我就像“什么?”,但它确实有效,所以这是重要的部分。好主意!
    • 哈哈,旋转它以使其“整洁”(一个变量 = 一列,一个观察值 = 一行)。然后更容易应用功能。但这有点令人困惑
    • 我觉得自己好蠢。这个 df 实际上是一个中间结果,我试图整理一些我已经旋转了更长的非常不整洁的数据(因此丑陋的名字)。我的想法是,我应该在更宽地旋转之前进行过滤,但后来我太专注于如何正确过滤,以至于后退一步意识到我应该先旋转然后过滤。
    • 一点也不傻!好处是您不需要重新旋转。 :)
    【解决方案2】:

    您的 anti_join 几乎很好,只是不要像那样将“元”变量放在 by = c(...) 中:

    df %>% 
      anti_join(.[is.na(.$value) & .$meta == "analyte", ], 
                by = c("Lots.of.cols", "analyte")) -> df
    

    结果:

    # A tibble: 3 x 5
      Lots.of.cols analyte meta    value KEEP 
             <dbl> <chr>   <chr>   <chr> <lgl>
    1            1 B       analyte 4     TRUE 
    2            1 B       unit    kg    TRUE 
    3            1 B       method  xxx   TRUE 
    

    【讨论】:

      【解决方案3】:

      我会先修复您的 KEEP 列,然后他们会通过它过滤数据。首先,我使用来自dplyrgroup_by() 按分析物对您的数据进行分组,我应用逻辑测试来发现在每组的某些行中是否有一行 meta = analyte 和 value = NA,我使用any() 函数用于发现这些测试结果中的任何一个在每组中是否为 TRUE。之后,我只需使用filter() 来选择所需的行。

      library(tidyverse)
      
      df <- df %>%
        group_by(analyte) %>% 
        mutate(KEEP = any(meta == "analyte" & is.na(value))) %>% 
        filter(KEEP == FALSE)
      

      结果如下:

      # A tibble: 3 x 5
      # Groups:   analyte [1]
        Lots.of.cols analyte meta    value KEEP 
               <dbl> <chr>   <chr>   <chr> <lgl>
      1            1 B       analyte 4     FALSE
      2            1 B       unit    kg    FALSE
      3            1 B       method  xxx   FALSE
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-15
        • 1970-01-01
        • 1970-01-01
        • 2017-06-09
        相关资源
        最近更新 更多