我一直在寻找解决方案并进行试验,但我似乎无法执行我应该做的简单任务。
我有两个数据框的格式类似于下面的玩具示例
DF1 = data.frame(A=c("cats","dogs",NA,"dogs"), B=c("kittens","puppies","kittens",NA), C=c(88,99,101,110))
A B C
1 cats kittens 88
2 dogs puppies 99
3 NA kittens 101
4 dogs NA 110
DF2 = data.frame(D=c(1,2), A=c("cats","dogs"), B=c("kittens","puppies"))
D A B
1 1 cats kittens
2 2 dogs puppies
Run Code Online (Sandbox Code Playgroud)
我希望合并两个数据集,这样输出是:
A B C D
1 cats kittens 88 1
2 dogs puppies 99 2
3 dogs NA 110 2
4 NA kittens 101 1
Run Code Online (Sandbox Code Playgroud)
换句话说,任何带有标签 A=="cats" 或 B=="kittens" 的行将被映射到 D 列中的 1,任何带有 A=="dogs" 或 B=="puppies" 的行将被映射到 2。
我已经使用了命令
merge(DF1, DF2, by=c("A","B"), all.x=TRUE)
Run Code Online (Sandbox Code Playgroud)
然而,这不正确匹配第 3 行和第 4 行,只有第 1 行和第 2 行。我得到输出
A B C D
1 cats kittens 88 1
2 dogs puppies 99 2
3 dogs NA 110 NA
4 NA kittens 101 NA
Run Code Online (Sandbox Code Playgroud)
请注意我正在使用的实际数据集很长。实际上,DF1 超过 1,000,000 行,DF2 超过 300,000 行,每行数千行,因此我真正需要的是可以缩放的解决方案。
这是一种不同的方法:
library(functional)
partial.merge <- function(DF1, DF2) {
common.cols <- intersect(names(DF1), names(DF2))
result.col <- names(DF2)[!(names(DF2) %in% common.cols)]
# This can only handle one result column:
stopifnot(length(result.col) == 1)
# Merge in each common column, one at a time.
# The identical operation is done for each common column, so Reduce is useful:
r <- Reduce(function(D, C) merge(D, DF2[c(C, result.col)], by=c(C), all.x=TRUE), x=common.cols, init=DF1)
# The merge created cols like c('D.x', 'D.y'). These are the columns:
merge.cols <- paste(result.col, c('x', 'y'), sep='.')
# The .x and .y columns are partial, put them together:
r[[result.col]] <- rowMeans(r[merge.cols], na.rm=TRUE)
# Remove the temporaries:
for (i in merge.cols) {
r[[i]] <- NULL
}
return(r)
}
partial.merge(DF1, DF2)
## B A C D
## 1 kittens cats 88 1
## 2 kittens <NA> 101 1
## 3 puppies dogs 99 2
## 4 <NA> dogs 110 2
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
940 次 |
| 最近记录: |