首页 > 解决方案 > 合并异构data.frames

问题描述

我正在尝试data.frames在 R中合并两个

d1 <- data.frame(Id=1:3,Name=c("Yann","Anne","Sabri"),Age=c(21,19,31),Height=c(178,169,192),Grade=c(15,12,18))
d2 <- data.frame(Id=c(1,3,4),Name=c("Yann","Sabri","Jui"),Age=c(28,21,15),Sex=c("M","M","F"),City=c("Paris","Paris","Toulouse"))

我想合并 by ,Id并在 final 中仅保留IdName、和列。AgeSexGradedata.frame

我想出了一个冗长的代码来完成这项工作,但有没有更好的方法?

dm <- data.frame(Id=unique(c(d1$Id,d2$Id)))
dm.d1.rows <- sapply(dm$Id, match, table = d1$Id)
dm.d2.rows <- sapply(dm$Id, match, table = d2$Id)
for(i in c("Name", "Age","Sex","Grade")) {
    if(i %in% colnames(d1) && is.factor(d1[[i]]) || i %in% colnames(d2) && is.factor(d2[[i]])) dm[[i]]<- factor(rep(NA,nrow(dm)),
            levels=unique(c(levels(d1[[i]]),levels(d2[[i]]))))
    else dm[[i]]<- rep(NA,nrow(dm))
    if(i %in% colnames(d1)) dm[[i]][!is.na(dm.d1.rows)] <- d1[[i]][na.exclude(dm.d1.rows)]
    if(i %in% colnames(d2)) dm[[i]][!is.na(dm.d2.rows)] <- d2[[i]][na.exclude(dm.d2.rows)]
}

标签: rdataframe

解决方案


这是通过提出的一个想法,使用该函数coalesce。此函数基本上用NA另一个(指定)列的值替换这些值。- 你可以在这里找到更多的信息和功能的实现coalesce

官方文档coalesce给定一组向量,coalesce() 在每个位置找到第一个非缺失值。这受到 SQL COALESCE 函数的启发,该函数对 NULL 执行相同的操作。


library(tidyverse)

d1 %>% 
 full_join(d2, by = c('Id', 'Name')) %>% 
 mutate(Age = coalesce(Age.x, Age.y)) %>% 
 select(Id, Name, Age, Sex, Grade)

这使,

  Id  Name Age  Sex Grade
1  1  Yann  21    M    15
2  2  Anne  19 <NA>    12
3  3 Sabri  31    M    18
4  4   Jui  15    F    NA

同样,在语法中,

library(data.table)

#Convert to data.tables
d1_t <- setDT(d1)
d2_t <- setDT(d2)

merge(d1_t, d2_t, by = c('Id', 'Name'), all = TRUE)[,
            Age := ifelse(is.na(Age.x), Age.y, Age.x)][, 
              c('Age.x', 'Age.y', 'City', 'Height') := NULL][]

这使,

   Id  Name Grade  Sex Age
1:  1  Yann    15    M  21
2:  2  Anne    12 <NA>  19
3:  3 Sabri    18    M  31
4:  4   Jui    NA    F  15  

推荐阅读