【问题标题】:Join based on a condition of another column根据另一列的条件加入
【发布时间】:2020-06-27 23:13:06
【问题描述】:

所以我想根据id加入df_1到df_2:

df_1 <- data.frame(id=c(1,2,3,4,5))


df_2<- data.frame(id=c(1,1,2,3,3,4,4,5,5,5,5),name=c("a","a1","b","c","c2","d","d1","e","e1","e2","e3"),status=c("IN","OUT","OUT","PENDING","OUT","OUT","REFER","IN","OUT","REFER","OUT"))

这就是我生成的数据集的样子:

df_merge<-data.frame(id=c(1,2,3,4,5),name=c("a","b","c","d1","e"))

所以我想合并与"IN" 关联的名称,如果不可用,则与"PENDING" 关联的名称,然后它应该是"REFER",如果这些都不存在,则将 id 与"OUT" 的状态。我怎样才能做到这一点?

【问题讨论】:

    标签: r merge conditional-statements


    【解决方案1】:

    我们做一个join,然后arrange by 'id' 和factor 按照指定的顺序用levels 转换'status',按'id'分组,得到slice的第一行

    library(dplyr)
    left_join(df_2, df_1) %>% 
      arrange(id, factor(status, levels = c('IN', 'PENDING', 'REFER', 'OUT'))) %>% 
      group_by(id) %>%
      slice(1) %>%
      ungroup %>%
      select(-status)
    # A tibble: 5 x 2
    #     id name 
    #  <dbl> <fct>
    #1     1 a    
    #2     2 b    
    #3     3 c    
    #4     4 d1   
    #5     5 e    
    

    如果 'df_1' 重复,则使用 distinct 行执行 left_join,稍后再执行 right_join

    df_1 <- data.frame(id=c(1,1,2,3,4,5,5)) 
    left_join(df_2, distinct(df_1)) %>% 
        arrange(id, factor(status, levels = c('IN', 'PENDING', 'REFER', 'OUT'))) %>%  
        group_by(id) %>%
        slice(1) %>%
        ungroup %>%
        select(-status)  %>%
        right_join(df_1)
    # A tibble: 7 x 2
    #     id name 
    #* <dbl> <fct>
    #1     1 a    
    #2     1 a    
    #3     2 b    
    #4     3 c    
    #5     4 d1   
    #6     5 e    
    #7     5 e   
    

    或者我们可以有一个list columnornestthe 'id' and theunnest`

    library(tidyr)
    df_1 %>% 
        group_by(id) %>% 
        nest %>%
        right_join(df_2) %>%
        arrange(id, factor(status, levels = c('IN', 'PENDING', 'REFER', 'OUT'))) %>%   
        group_by(id) %>%
        slice(1) %>%
        ungroup %>%
        select(-status) %>% 
        unnest
    

    或使用data.table

    library(data.table)
    setDT(df_2)[df_1,  .(name = name[order(match(status,
          c('IN', 'PENDING', 'REFER', 'OUT')))[1]]), on = .(id), by = .EACHI]
    #   id name
    #1:  1    a
    #2:  2    b
    #3:  3    c
    #4:  4   d1
    #5:  5    e
    

    或者base R选项是先order'df_2'数据集,然后根据'id'中的duplicated元素提取'name'的元素

    df_2n <- df_2[order(df_2$id, factor(df_2$status, levels = c('IN', 'PENDING', 'REFER', 'OUT'))),] 
    df_1$name <-  df_2n$name[!duplicated(df_2$id)]
    

    【讨论】:

    • 谢谢你,你总是有很好的解决方案。只有一个问题,如果我的状态没有反映在 df_2 中,我是否也必须将其包含在级别声明中?例如,我有“未找到”。
    • 如果每个 ID 有多行怎么办?例如,我有 df_1
    • @Mel 如果在组中未找到任何预期级别,您可以使用条件 if/else 创建“未找到”。如果每个 ID 有多个行,则不能使用 join,因为不清楚要匹配哪一行。在这种情况下,逻辑应该改变。这取决于您要如何制作逻辑
    • @Mel 对于新数据集的预期是什么?这里,不清楚
    • 逻辑保持不变,但我不想每个 id 有一行。 df_merge
    猜你喜欢
    • 2019-12-22
    • 2021-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多