合并具有所有组合的两个数据框

Posted

技术标签:

【中文标题】合并具有所有组合的两个数据框【英文标题】:Merge two data frames with all combinations 【发布时间】:2016-10-19 06:09:51 【问题描述】:

我遇到了一个复杂的问题: 我有两个数据框,它们有 4 台不同机器的 no 和规范(颜色、零件)的一种组合。每台机器总共有 5 个规格(实际上更多的机器和规格)。 以下是两个示例数据框:

df1 <- data.frame( 
  nr=c("000", "000", "000", "001", "002",
       "002", "003", "004", "004", "004", "005"), 
  Color=c("Red", "Cyan", "Brown", "Blue", "Red",
          "Green", "DeepBlue", "Orange", "Cyan", "Grey", "Magenta"), 
  mach1=c(1, NA, NA, 1, NA, 1, 1, NA, 1, NA, 1),  
  mach2=c(1, NA, NA, 1, NA, 1, 1, 1, NA, NA, 1),  
  mach3=c(NA, 1, NA, 1, 1, NA, 1, NA, NA, 1, 1),  
  mach4=c(NA, NA, 1, 1, NA, 1, 1, NA, NA, 1, 1))

df2 <- data.frame( 
  nr=c("000", "000", "001", "002", "002",
       "003", "003", "004", "005", "005"), 
  Part=c("Car", "Tree", "Flag", "Tree", "Road",
         "Road", "House", "Plane", "House", "Car"), 
  mach1=c(NA, 1, 1, NA, 1, NA, 1, 1, NA, 1),  
  mach2=c(1, NA, 1, NA, 1, NA, 1, 1, 1, NA),  
  mach3=c(NA, 1, 1, 1, NA, 1, NA, 1, 1, NA),  
  mach4=c(NA, 1, 1, 1, NA, 1, NA, 1, 1, NA))

所以我有这些输出:

> df1
    nr    Color mach1 mach2 mach3 mach4
1  000      Red     1     1    NA    NA
2  000     Cyan    NA    NA     1    NA
3  000    Brown    NA    NA    NA     1
4  001     Blue     1     1     1     1
5  002      Red    NA    NA     1    NA
6  002    Green     1     1    NA     1
7  003 DeepBlue     1     1     1     1
8  004   Orange    NA     1    NA    NA
9  004     Cyan     1    NA    NA    NA
10 004     Grey    NA    NA     1     1
11 005  Magenta     1     1     1     1
> df2
    nr  Part mach1 mach2 mach3 mach4
1  000   Car    NA     1    NA    NA
2  000  Tree     1    NA     1     1
3  001  Flag     1     1     1     1
4  002  Tree    NA    NA     1     1
5  002  Road     1     1    NA    NA
6  003  Road    NA    NA     1     1
7  003 House     1     1    NA    NA
8  004 Plane     1     1     1     1
9  005 House    NA     1     1     1
10 005   Car     1    NA    NA    NA

现在我想将这两个数据帧组合成一个新的数据帧 df3,它显示特定机器的颜色和零件的所有组合,如下所示:

> df3
    nr    Color  Part mach1 mach2 mach3 mach4
1  000      Red  Tree     1    NA    NA    NA
2  000      Red   Car    NA     1    NA    NA
3  000     Cyan  Tree    NA    NA     1    NA
4  000    Brown  Tree    NA    NA    NA     1
5  001     Blue  Flag     1     1     1     1
6  002    Green  Road     1     1    NA    NA
7  002      Red  Tree    NA    NA     1    NA
8  002    Green  Tree    NA    NA    NA     1
9  003 Deepblue House     1     1    NA    NA
10 003 Deepblue  Road    NA    NA     1     1
11 004     Cyan Plane     1    NA    NA    NA
12 004   Orange Plane    NA     1    NA    NA
13 004     Grey Plane    NA    NA     1     1
14 005  Magenta   Car     1    NA    NA    NA
15 005  Magenta House    NA     1     1     1
> 

有什么建议吗?

【问题讨论】:

【参考方案1】:

您可以先重塑两个数据框(使用reshape2 中的melt),然后合并它们(使用dplyr 中的full_join)并将其重塑回原始格式:

library(dplyr)
library(reshape2)

df1.b <- melt(df1)
df2.b <- melt(df2)

df3 <- full_join(df1.b, df2.b)

df3 <- na.omit(df3)

df3.b <- dcast(df3, nr + Color + Part ~ variable)

    nr    Color  Part mach1 mach2 mach3 mach4
1  000    Brown  Tree    NA    NA    NA     1
2  000     Cyan  Tree    NA    NA     1    NA
3  000      Red   Car    NA     1    NA    NA
4  000      Red  Tree     1    NA    NA    NA
5  001     Blue  Flag     1     1     1     1
6  002    Green  Road     1     1    NA    NA
7  002    Green  Tree    NA    NA    NA     1
8  002      Red  Tree    NA    NA     1    NA
9  003 DeepBlue House     1     1    NA    NA
10 003 DeepBlue  Road    NA    NA     1     1
11 004     Cyan Plane     1    NA    NA    NA
12 004     Grey Plane    NA    NA     1     1
13 004   Orange Plane    NA     1    NA    NA
14 005  Magenta   Car     1    NA    NA    NA
15 005  Magenta House    NA     1     1     1

【讨论】:

【参考方案2】:

与@beetroot 相同的想法,使用base R reshape()merge() 实现:

reshape(na.omit(merge(
  reshape(df1,dir='l',idvar=c('nr','Color'),varying=grep('^mach',names(df1)),v.names='mach'),
  reshape(df2,dir='l',idvar=c('nr','Part'),varying=grep('^mach',names(df2)),v.names='mach')
)),dir='w',idvar=c('nr','Color','Part'),sep='');
##     nr    Color  Part mach1 mach2 mach3 mach4
## 1  000      Red  Tree     1    NA    NA    NA
## 4  000      Red   Car    NA     1    NA    NA
## 7  000     Cyan  Tree    NA    NA     1    NA
## 10 000    Brown  Tree    NA    NA    NA     1
## 13 001     Blue  Flag     1     1     1     1
## 17 002    Green  Road     1     1    NA    NA
## 21 002      Red  Tree    NA    NA     1    NA
## 23 002    Green  Tree    NA    NA    NA     1
## 25 003 DeepBlue House     1     1    NA    NA
## 27 003 DeepBlue  Road    NA    NA     1     1
## 29 004     Cyan Plane     1    NA    NA    NA
## 30 004   Orange Plane    NA     1    NA    NA
## 31 004     Grey Plane    NA    NA     1     1
## 33 005  Magenta   Car     1    NA    NA    NA
## 34 005  Magenta House    NA     1     1     1

(如有必要,可以在之后修改行名。)

【讨论】:

以上是关于合并具有所有组合的两个数据框的主要内容,如果未能解决你的问题,请参考以下文章

将两个数据框与一些公共列合并,其中公共的组合需要是自定义函数

如何对联合数据框进行分组以组合相同的行

如何基于两列组合两个数据框? [复制]

如何合并具有相同列名的多个数据框?

在R中组合两个具有不同行数的数据框[重复]

Python:如何合并两个不同大小的数据框? [复制]