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]