R 合并不同大小的数据帧
我有两个数据帧分别为R 合并不同大小的数据帧,r,dataframe,R,Dataframe,我有两个数据帧分别为d1和d2: x y z 10 10 7 10 12 6 11 10 8 11 12 2 12 10 1 12 12 5 x y z 10 10 100 11 10 200 12 12 400 我想要像这样的东西: x y z 10 10 100 10 12 6 11 10 200 11 12 2 12 10 1 12 12 400 对于这个琐碎的问题我真的很抱歉,我无法得到答案 从您的描述中,我了解到当x和y匹配时,您希望将d1
d1
和d2
:
x y z
10 10 7
10 12 6
11 10 8
11 12 2
12 10 1
12 12 5
x y z
10 10 100
11 10 200
12 12 400
我想要像这样的东西:
x y z
10 10 100
10 12 6
11 10 200
11 12 2
12 10 1
12 12 400
对于这个琐碎的问题我真的很抱歉,我无法得到答案 从您的描述中,我了解到当
x
和y
匹配时,您希望将d1
中的z
值替换为d2
中的z
值
使用基本R:
d3 <- merge(d1, d2, by = c("x","y"), all.x = TRUE)
d3[is.na(d3$z.y),"z.y"] <- d3[is.na(d3$z.y),"z.x"]
d3 <- d3[,-3]
names(d3)[3] <- "z"
使用data.table-package: 或一次性:
setDT(d1)[setDT(d2), on = .(x, y), z := i.z]
其中:
> d3
x y z
1 10 10 100
2 10 12 6
3 11 10 200
4 11 12 2
5 12 10 1
6 12 12 400
> d1
x y z
1: 10 10 100
2: 10 12 6
3: 11 10 200
4: 11 12 2
5: 12 10 1
6: 12 12 400
使用dplyr包:
听起来您想确保每个
x
和y
值只有一个z
值。主要问题是如何选择与其关联的z值。根据描述,我猜您要么希望第二个数据帧始终覆盖,要么希望取最大值
从原始数据开始:
df1 <- structure(list(x = c(10L, 10L, 11L, 11L, 12L, 12L), y = c(10L, 12L, 10L, 12L, 10L, 12L), z = c(7L, 6L, 8L, 2L, 1L, 5L)), .Names = c("x", "y", "z"), class = "data.frame", row.names = c(NA, -6L))
df2 <- structure(list(x = 10:12, y = c(10L, 10L, 12L), z = c(100L, 200L,400L)), .Names = c("x", "y", "z"), class = "data.frame", row.names = c(NA,-3L))
相反,如果希望第二个数据帧覆盖第一个数据帧,则将使用要匹配的最后一个值进行聚合
merged.df <- aggregate(z ~ x+ y, data=rbind(df1, df2), function(d) tail(d, n=1))
使用data.table
require(data.table)
merged.df <- setDT(rbind(df1, df2))[, lapply(.SD, last), .(x,y)]
require(data.table)
merged.df位于优秀的wrt数据表之上
在data.table中,您可以使用键进行连接,而对于data.table,使用键进行任何操作都是最快的选择。您甚至可以有不同的列名,请参见下面修改的示例
大致说来,数据:
x y z
10 10 100
11 10 200
12 12 400
x q z
10 10 7
10 12 6
11 10 8
11 12 2
12 10 1
12 12 5
和代码:
library(data.table)
d1 <- fread("d1.csv", sep=" ")
d2 <- fread("d2.csv", sep=" ")
# here is data.table keys magic
# note different column names
setkey(d1, x, q)
setkey(d2, x, y)
q <- d2[d1][is.na(z), z := i.z][, i.z := NULL]
print(q)
或者使用merge
此更新联接可以在base中完成,方法是使用match
和which
查找用于对表进行子设置的索引,并使用interaction
从两个关键向量中生成一个关键向量
通过这种方式,d1
的顺序和大小都不会改变。如果d2
中的一个键出现两次,则第一次出现将用于更新d1
d1 <- read.table(header=TRUE, text="x y z
10 10 7
10 12 6
11 10 8
11 12 2
12 10 1
12 12 5")
d2 <- read.table(header=TRUE, text="x y z
10 10 100
11 10 200
12 12 400")
key <- c("x", "y") #define which columns are used as matching key
idx <- match(interaction(d2[key]), interaction(d1[key])) #find where it matches
d1$z[idx] <- d2$z #make the update
d1 #show result
# x y z
#1 10 10 100
#2 10 12 6
#3 11 10 200
#4 11 12 2
#5 12 10 1
#6 12 12 400
d1只需删除d1和rbind(d1,d2)的第一行、第三行和最后一行,您能详细说明10,10,7发生了什么吗?前两列是“键”还是第三列是“值”?亲爱的MLavoie,这只是一个例子。真实的数据更大。亲爱的mlt,x和y是经度和纬度,z是值,我的意思是,对于给定的x和y,它可以是多值的吗?请考虑亲爱的用户265691,非常感谢大家分享有用的信息。我还添加了一个dplyr
alternative@Jaap我已经添加了扩展示例的答案,请参见below@Jaap在dplyr版本v0.5.0()中添加了coalesce
功能。这可以简化您的dplyr解决方案:d3%变异(z=coalesce(z.y,z.x))%%>%选择(-c(z.x,z.y))
@laurehostert Thx进行通知!我现在已经把它包括在我的答案中了。亲爱的Severin Pappadeux,谢谢你的改进建议。当你在
上使用时,你也可以加入不同的列名:d2[d1,on=c(“x”=“x”,“y”=“q”)]
。通过使用,您可以将其缩短为d2[d1,on=c(“x”,“y”=“q”)]
。不确定设置关键点是否比在
上使用快。您测试过了吗?很好,但它首先返回一个全新的data.table,然后更新它——所有这些都只是为了添加一列(=内存效率低下)。请参阅Jaap的更新答案。
require(dplyr)
merged.df <- rbind(df1, df2) %>% group_by(x, y) %>% summarise_each(funs(last))
require(data.table)
merged.df <- setDT(rbind(df1, df2))[, lapply(.SD, last), .(x,y)]
x y z
10 10 100
11 10 200
12 12 400
x q z
10 10 7
10 12 6
11 10 8
11 12 2
12 10 1
12 12 5
library(data.table)
d1 <- fread("d1.csv", sep=" ")
d2 <- fread("d2.csv", sep=" ")
# here is data.table keys magic
# note different column names
setkey(d1, x, q)
setkey(d2, x, y)
q <- d2[d1][is.na(z), z := i.z][, i.z := NULL]
print(q)
x y z
1: 10 10 100
2: 10 12 6
3: 11 10 200
4: 11 12 2
5: 12 10 1
6: 12 12 400
d1 <- read.table(header=TRUE, text="x y z
10 10 7
10 12 6
11 10 8
11 12 2
12 10 1
12 12 5")
d2 <- read.table(header=TRUE, text="x y z
10 10 100
11 10 200
12 12 400")
key <- c("x", "y") #define which columns are used as matching key
idx <- match(interaction(d2[key]), interaction(d1[key])) #find where it matches
d1$z[idx] <- d2$z #make the update
d1 #show result
# x y z
#1 10 10 100
#2 10 12 6
#3 11 10 200
#4 11 12 2
#5 12 10 1
#6 12 12 400
idx <- match(interaction(d1[key]), interaction(d2[key]))
idxn <- which(!is.na(idx)) #find where it does not match
d1$z[idxn] <- d2$z[idx[idxn]]
idx <- match(interaction(d2[key]), interaction(d1[key]))
idxn <- which(!is.na(idx))
d1$z[idx[idxn]] <- d2$z[idxn]