• R合并数据框有重复匹配时只保留第一行


    前言

    合并数据框有重复匹配时通常会返回所有的匹配,如何只保留匹配的第一行呢?其实这个需求也很常见。如芯片探针ID和基因ID往往多对一,要合并ID对应矩阵和芯片表达矩阵时。

    数据例子

    data = data.frame(id = c(1,2,3,4,5),
                      state = c("KS","MN","AL","FL","CA"))
    scores = data.frame(id = c(1,1,1,2,2,3,3,3),
                        score = c(66,75,78,86,85,76,75,90))
    

    数据长这样:

    想要这样的结果:

    错误的尝试

    试了不少方法,以下都是达不到需求的:

    dplyr::left_join(data,scores,by="id")
    dplyr::inner_join(data,scores,by="id")
    dplyr::left_join(data, scores, by="id", match="first") 
    
    merge(data, scores, by = "id")                  
    dplyr::semi_join(data, scores, by = "id") 
    
    #distinct去重
    dplyr::left_join(data, dplyr::distinct(scores, id, .keep_all = T))
    data %>% dplyr::left_join(dplyr::distinct(scores, id, .keep_all = T)) %>% 
      tidyr::replace_na(replace = list("score"=0L)) #替换na
    

    正确方法

    通过网上查找,找到了如下实现方式:

    方法1

    require(data.table)
    setDT(scores); setDT(data) # convert to data.tables by reference
    scores[data, mult = "first", on = "id", nomatch=0L]
    
    #注意两者顺序
    data[scores, mult = "first", on = "id", nomatch=0L] #达不到要求
    

    方法2

    merge(data, aggregate(score ~ id, data=scores, head, 1), by="id") 
    

    方法3

    merge(data, scores[!duplicated(scores$id),], by="id")
    

    方法4

    #Return also those which found no match
    tt <- cbind(data, score=scores[match(data$id, scores$id),"score"])
    #Return only those which found a match
    tt[!is.na(tt$score),]
    

    总结

    个人最钟意第一种方法,因为data.table真的适合处理大数据,相比于join和merge等快了不少,几千万个基因探针我用join处理的话要很久很久,而且占的内存超级大。data.table几分钟就处理完了。

    不过data.table的语法感觉怪怪的,所以一直没去学,看来要好好学习一下了。

  • 相关阅读:
    分布式哈希和一致性哈希算法
    消息队列rabbitmq的五种工作模式(go语言版本)
    Mysql查询缓存
    数据库的三大设计范式
    二叉树的常见算法
    消息队列选型分析
    Mysql防止索引失效原则
    Mysql索引优化单表、两表、三表实践
    数据结构 【栈与队列】
    谷歌实用插件
  • 原文地址:https://www.cnblogs.com/jessepeng/p/11072533.html
Copyright © 2020-2023  润新知