合并具有重复列的两个数据帧

时间:2013-12-04 11:43:46

标签: r merge

我有几个.csv文件,每个文件对应一个月度客户列表和一些有关它们的信息。每个文件都包含有关客户的相同信息,例如:

names(data.jan)

ID     AGE      CITY      GENDER

names(data.feb)

ID     AGE      CITY      GENDER

为简化起见,我将只考虑两个月,一月和二月,但我真正的csv文件集从1月到11月:

考虑到“客户X”,我有三种可能的情况:

1-客户X列在1月数据库中,但他离开了,现在未在2月份列出 2-客户X列在1月和2月的数据库中 3-客户X在二月份进入数据库,所以他没有在一月份上市

我遇到了以下问题:我需要创建一个包含所有客户的数据库及其在两个数据框中列出的相应信息。但是,考虑到两个数据框中列出的客户,我想从他的第一个条目,即1月份中选择他的信息。

当我使用合并时,我有四个选项,根据http://www.dummies.com/how-to/content/how-to-use-the-merge-function-with-data-sets-in-r.html

Merge options

data <- merge(data.jan,data.feb, by="ID", all=TRUE)

无论选择哪一项,all.x或all.y,我都会获得相同的不需要的输出,称为数据:

data[1,]

ID     AGE.x      CITY.x      GENDER.x       AGE.y      CITY.y      GENDER.y
123      25         NY           M            25          NY            M

我认为这里可行的方法是将这两种数据库与这种类型的连接合并:

enter image description here

然后,将结果数据帧与data.jan合并为完整外连接。但我不知道如何在R中编码。

谢谢,

伯纳

3 个答案:

答案 0 :(得分:1)

 d1 <- data.frame(x=1:9,y=1:9,z=1:9)
 d2 <- data.frame(x=1:10,y=11:20,z=21:30) # example data
 d3 <- merge(d1,d2, by="x", all=TRUE) #merge


# keep the original columns from janary (i.e. y.x, z.x)
# but replace the NAs in those columns with the data from february (i.e. y.y,z.y )
d3[is.na(d3[,2]) ,][,2:3] <- d3[is.na(d3[,2]) ,][, 4:5]
#>  d3[, 1:3]
#    x y.x z.x
#1   1   1   1
#2   2   2   2
#3   3   3   3
#4   4   4   4
#5   5   5   5
#6   6   6   6
#7   7   7   7
#8   8   8   8
#9   9   9   9
#10 10  20  30

这可能会超过2个月,但也许您应该考虑@ flodel的评论,还要注意当您的原始Jan数据有NA时有恶意(并且您仍然想要第一个)几个月的数据,NA或未保留,但保留),但您在问题中从未提及过这些数据。

答案 1 :(得分:0)

尝试:

data <- merge(data.jan,data.frame(ID=data.feb$ID), by="ID")

虽然我没有测试它,因为没有数据,但如果你只是加入2月份的ID col,它应该只筛选出不在两个帧中的任何东西

答案 2 :(得分:0)

@ user1317221_G的解决方案非常棒。如果您的表很大(很多客户),数据表可能会更快:

library(data.table)
#  some sample data
jan <- data.table(id=1:10,  age=round(runif(10,25,55)), city=c("NY","LA","BOS","CHI","DC"), gender=rep(c("M","F"),each=5))
new <- data.table(id=11:16, age=round(runif(6,25,55)), city=c("NY","LA","BOS","CHI","DC","SF"), gender=c("M","F"))
feb <- rbind(jan[6:10,],new)
new <- data.table(id=17:22, age=round(runif(6,25,55)), city=c("NY","LA","BOS","CHI","DC","SF"), gender=c("M","F"))
mar <- rbind(jan[1:5,],new)

setkey(jan,id)
setkey(feb,id)

join <- data.table(merge(jan, feb, by="id", all=T))
join[is.na(age.x) , names(join)[2:4]:= join[is.na(age.x),5:7,with=F]]

修改:这会增加多个月的处理时间。

f <- function(x,y) {
  setkey(x,id)
  setkey(y,id)
  join <- data.table(merge(x,y,by="id",all=T))
  join[is.na(age.x) , names(join)[2:4]:= join[is.na(age.x),5:7,with=F]]
  join[,names(join)[5:7]:=NULL]                # get rid of extra columns
  setnames(join,2:4,c("age","city","gender"))  # rename columns that remain
  return(join)
}

Reduce("f",list(jan,feb,mar))

Reduce(...)依次将函数f(...)应用于列表的元素,首先是janfeb,然后是结果mar等等。