【问题标题】:dplyr case_when across groupsdplyr case_when 跨组
【发布时间】:2020-08-12 14:24:24
【问题描述】:

我有 df

df = data.frame(
    group = c(rep("A", 3), rep("B", 3)), 
    vt = c("SO:0001574", "SO:0001619", "SO:0001619", "SO:0001619", "SO:0001619", "SO:0001821")
    )

还有两个向量:

tier_1 = c("SO:0001574", "SO:0001575")
tier_2 = c("SO:0001821", "SO:0001822")

我想产生一个输出:

  group         vt     ct
1     A SO:0001574 tier_1
2     A SO:0001619 tier_1
3     A SO:0001619 tier_1
4     B SO:0001619 tier_2
5     B SO:0001619 tier_2
6     B SO:0001821 tier_2

即我想生成第三列 ct,它是根据 tier_1 或 tier_2 中 vt 列的存在来填充的,这样给定组中的所有行都填充有该层类型。

我试过了:

df %>%
    dplyr::group_by(group) %>% 
    dplyr::mutate(tier = dplyr::case_when(
        vt %in% tier_1 ~ "tier_1",
        vt %in% tier_2 ~ "tier_2"))

但这只会填充单个行,而不是组内的所有行:

# A tibble: 6 x 4
# Groups:   group [2]
  group vt         ct     tier  
  <chr> <chr>      <chr>  <chr> 
1 A     SO:0001574 tier_1 tier_1
2 A     SO:0001619 tier_1 NA    
3 A     SO:0001619 tier_1 NA    
4 B     SO:0001619 tier_2 NA    
5 B     SO:0001619 tier_2 NA    
6 B     SO:0001821 tier_2 tier_2

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    将代码包装在any 中以获得每组一个逻辑值:

    library(dplyr)
    
    df %>%
     group_by(group) %>% 
     mutate(tier = case_when(
                    any(vt %in% tier_1) ~ "tier_1",
                    any(vt %in% tier_2) ~ "tier_2"))
    
    #  group vt         tier  
    #  <chr> <chr>      <chr> 
    #1 A     SO:0001574 tier_1
    #2 A     SO:0001619 tier_1
    #3 A     SO:0001619 tier_1
    #4 B     SO:0001619 tier_2
    #5 B     SO:0001619 tier_2
    #6 B     SO:0001821 tier_2
    

    【讨论】:

      【解决方案2】:

      您还可以在您描述的第一步之后在{tidyr} 中使用fill()

      library(tidyr)
      library(dplyr)
      
      df = data.frame(
        group = c(rep("A", 3), rep("B", 3)), 
        vt = c("SO:0001574", "SO:0001619", "SO:0001619", "SO:0001619", "SO:0001619", "SO:0001821")
      )
      tier_1 = c("SO:0001574", "SO:0001575")
      tier_2 = c("SO:0001821", "SO:0001822")
      
      df %>%
        group_by(group) %>% 
        mutate(tier = case_when(
          vt %in% tier_1 ~ "tier_1",
          vt %in% tier_2 ~ "tier_2")) %>%
        fill(tier, .direction = "updown") %>%
        ungroup()
      
      # A tibble: 6 x 3
      # Groups:   group [2]
      #  group vt         tier  
      #  <chr> <chr>      <chr> 
      #1 A     SO:0001574 tier_1
      #2 A     SO:0001619 tier_1
      #3 A     SO:0001619 tier_1
      #4 B     SO:0001619 tier_2
      #5 B     SO:0001619 tier_2
      #6 B     SO:0001821 tier_2
      

      【讨论】:

        猜你喜欢
        • 2020-09-16
        • 1970-01-01
        • 2022-11-09
        • 1970-01-01
        • 2018-05-31
        • 1970-01-01
        • 2021-09-20
        • 2020-02-24
        • 1970-01-01
        相关资源
        最近更新 更多