根据上面的讨论和答案,这是我使用 dplyr
的方式。代码不是最干净的,是的,我确实使用了 suppressWarnings()
。
对于 OP 的可重现示例:
set.seed(1)
missings <- sample.int(6, 3)
df1 <- data.frame(ID = letters[1:6], V1 = NA)
df2 <- data.frame(ID = letters[1:6], V1 = NA)
df1$V1[missings] <- rnorm(3)
df2$V1[setdiff(1:6, missings)] <- rnorm(3)
简单的解决方案:
library(dplyr)
library(reshape2)
coalesce <- function(...) {
apply((...), 1, function(x) {
x[which(!is.na(suppressWarnings(as.numeric(x))))[1]]
})
}
full_join(df1, df2, by = 'ID') %>% mutate(V1 = coalesce(.)) %>% select(.,ID,V1)
ID V1
1 a -1.5399500
2 b 1.3297993
3 c 0.4146414
4 d -0.9285670
5 e -0.2947204
6 f 1.2724293
对于具有多个变量的一般解决方案(这里展示了3个):
set.seed(1)
df1 <- data.frame(ID = letters[1:6], V1 = NA, V2 = NA, V3 = NA)
df2 <- data.frame(ID = letters[1:6], V1 = NA, V2 = NA, V3 = NA)
df1$V1[sample.int(6, 3)] <- rnorm(3)
df2$V1[setdiff(1:6, sample.int(6, 3))] <- rnorm(3)
df1$V2[sample.int(6, 3)] <- rnorm(3)
df2$V2[setdiff(1:6, sample.int(6, 3))] <- rnorm(3)
df1$V3[sample.int(6, 3)] <- rnorm(3)
df2$V3[setdiff(1:6, sample.int(6, 3))] <- rnorm(3)
同样的coalesce()
函数,更加详细的dplyr
逻辑:
library(dplyr)
library(reshape2)
coalesce <- function(...) {
apply((...), 1, function(x) {
x[which(!is.na(suppressWarnings(as.numeric(x))))[1]]
})
}
full_join(df1, df2, by = "ID") %>%
melt(., id.vars = "ID") %>%
mutate(var = substr(as.character(variable),0,2)) %>%
group_by(var,value) %>%
dcast(.,ID + var ~ variable, value.var = "value") %>%
mutate(c = coalesce(.)) %>%
dcast(.,ID ~ var, value.var = "c")
ID V1 V2 V3
1 a -1.5399500 0.3898432 <NA>
2 b -0.9285670 -0.3053884 0.80418951
3 c -0.8356286 <NA> 0.5939013
4 d 0.1836433 -0.4115108 -0.05710677
5 e <NA> <NA> 0.8212212
6 f -0.6264538 1.5117812 0.9189774
coalesce()
函数选择第一个非NA值(如果存在)。根据问题,您可以选择
max
或其他内容。合并数据集中的
ID
列或任何其他列必须是非数字的。希望这对解决您的实际问题有所帮助。
coalesce
函数来优先考虑其中一个 - 在此处查看 R 中coalesce
的实现。当然,如果它们是互补的,它仍然可以正常工作。 - Gregor Thomasdplyr
的开发版本已经实现了coalesce
函数,因此您可以直接使用dplyr::coalesce(df1, df2)
。 - Steven Beaupréna.omit(rbind(df1, df2))
这样的方法也可以(等同于merge(na.omit(df1), na.omit(df2), by = 'ID')
,您差不多已经展示了)。不确定为什么那种方法不令人满意。您是否想保留其他列中可能缺失的值? - Gregor Thomas