【问题标题】:Looking for a dplyr function to apply a filter conditionally寻找一个 dplyr 函数来有条件地应用过滤器
【发布时间】:2020-07-06 18:33:54
【问题描述】:

我有一个包含各种血液学值及其采集时间的数据框。这些值应该只在特定时间收集,但偶尔会添加一个额外的值。我想删除在计划时间之外收集值的任何实例。

为了说明这个问题,这里有一些代码来创建我正在使用的数据框的一个非常简化的版本(加上一些示例时间表):

example <- tibble("Parameter" = c(rep("hgb", 3), rep("bili", 3), rep("LDH", 3)), 
                  "Collection" = c(1, 3, 4, 1, 5, 6, 0, 4, 8))

hgb_sampling <- c(1, 4)
bili_sampling <- c(1, 5)
ldh_sampling <- c(0, 4)

因此,我需要一种方法来根据“参数”列中的值有条件地应用过滤器。该解决方案需要适合 dyplr 管道并产生如下内容:

filtered <- tibble("Parameter" = c(rep("hemoglobin", 2), rep("bilirubin", 2), rep("LDH", 2)), 
                  "Collection" = c(1, 4, 1, 5, 0, 4))

我已经尝试了几件事(它们都类似于下面的内容)但是使用“参数”会出错:

df <- example %>%
  {if (Parameter == "hgb") filter(., Collection %in% hgb_sampling)} 

有什么建议吗?

【问题讨论】:

  • 这些采样值是最小值、最大值还是只是精确值?因为你提到了集合

标签: r dplyr tidyverse


【解决方案1】:

涉及dplyrstringrtibble 的选项可能是:

enframe(mget(ls(pattern = "sampling"))) %>%
 mutate(name = str_extract(name, "[^_]+")) %>%
 right_join(example %>%
             mutate(Parameter = tolower(Parameter)), by = c("name" = "Parameter")) %>%
 filter(Collection %in% unlist(value)) %>%
 select(-value)

  name  Collection
  <chr>      <dbl>
1 hgb            1
2 hgb            4
3 bili           1
4 bili           5
5 ldh            0
6 ldh            4

如果存储在单独的 df 中,如 @Ronak Shah 所示,那么您可以这样做:

example %>%
 filter(Collection %in% unlist(ref_df$value[match(Parameter, ref_df$Parameter)]))

【讨论】:

    【解决方案2】:

    您可以创建一个引用 tibble,将其与 example 连接并仅保留选定的行。

    library(dplyr)
    
    ref_df <- tibble::tibble(Parameter = c("hgb","bili", "LDH"), 
                             value  = list(c(1, 4), c(1, 5), c(0, 4)))
    
    example %>%
      inner_join(ref_df, by = 'Parameter') %>%
      group_by(Parameter) %>%
      filter(Collection %in% unique(unlist(value))) %>%
      select(Parameter, Collection)
    
    #  Parameter Collection
    #  <chr>          <dbl>
    #1 hgb                1
    #2 hgb                4
    #3 bili               1
    #4 bili               5
    #5 LDH                0
    #6 LDH                4
    

    【讨论】:

      【解决方案3】:

      将您的有效时间放入与Collection 中的名称匹配的列表中,然后按Collection 中的值分组并按sample_list 中每个列表元素的值进行过滤:

      sample_list <- list(hgb = c(1, 4), bili = c(1, 5), LDH = c(0, 4))
      
      example %>% 
          group_by(Parameter) %>% 
          filter(Collection %in% sample_list[[first(Parameter)]])
      

      输出:

      # A tibble: 6 x 2
        Parameter  Collection
        <chr>           <dbl>
      1 hemoglobin          1
      2 hemoglobin          4
      3 bilirubin           1
      4 bilirubin           5
      5 LDH                 0
      6 LDH                 4
      

      【讨论】:

        【解决方案4】:

        其他解决方案

        library(tidyverse)
        library(purrr)
        fltr <- list(hgb = c(1, 4), bili = c(1, 5), LDH = c(0,4)) %>% 
          enframe(name = "Parameter")
        
        example %>% 
          group_by(Parameter) %>% 
          nest() %>% 
          left_join(fltr) %>% 
          mutate(out = map2(.x = data, .y = value, .f = ~ filter(.x, Collection %in% .y))) %>% 
          unnest(out) %>% 
          select(Parameter, Collection)
        

        【讨论】:

          【解决方案5】:

          简单的方法,很容易修改、添加、删除、调试……

          library(dplyr)
          
          example %>%
            filter(Parameter=="hgb" & Collection %in% c(1, 4) |
                   Parameter=="bili" & Collection %in% c(1, 5) |
                   Parameter=="LDH" & Collection %in% c(0, 4) )
          

          或者,如果您希望值在一个范围内:

          example %>%
            filter(Parameter=="hgb" & between(Collection, 1, 4) |
                   Parameter=="bili" & between(Collection, 1, 5) |
                   Parameter=="LDH" & between(Collection, 0, 4))
          

          【讨论】:

          • 简单点。谢谢。
          • 顺便说一句,这正是我修复已损坏 2 周的代码所需要的。谢谢。
          【解决方案6】:

          试试purrr::imap_dfr:

          library(tidyverse)
          
          example <- tibble("Parameter" = c(rep("hgb", 3), rep("bili", 3), rep("LDH", 3)), 
                            "Collection" = c(1, 3, 4, 1, 5, 6, 0, 4, 8))
          
          l <- list(hgb = c(1, 4), bili = c(1, 5), LDH = c(0, 4))
          
          imap_dfr(l, ~example %>%
                     filter(Parameter == .y & Collection %in% .x))
          
          # # A tibble: 6 x 2
          # Parameter Collection
          # <chr>          <dbl>
          #   1 hgb                1
          # 2 hgb                4
          # 3 bili               1
          # 4 bili               5
          # 5 LDH                0
          # 6 LDH                4
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-01-30
            • 1970-01-01
            • 1970-01-01
            • 2021-04-14
            • 2020-04-17
            • 2017-05-06
            • 1970-01-01
            相关资源
            最近更新 更多