我想有效地对两个数据帧的条目求和,尽管不保证数据帧具有相同的维度或列名称。合并并不是我在这之后的真实情况。相反,我想创建一个输出对象,其中包含属于任一添加数据帧的所有行和列名称。在该输出的每个位置,我想对计算值使用以下逻辑:
例如,请考虑以下输入数据框:
df1 = data.frame(x = c(1,2,3), y = c(4,5,6))
rownames(df1) = c("a", "b", "c")
df2 = data.frame(x = c(7,8), z = c(9,10), w = c(2, 3))
rownames(df2) = c("a", "d")
> df1
x y
a 1 4
b 2 5
c 3 6
> df2
x z w
a 7 9 2
d 8 10 3
我希望最终结果是
> df2
x y z w
a 8 4 9 2
b 2 5 0 0
c 3 6 0 0
d 8 0 10 3
到目前为止我做了什么 -
dplyr中的bind_rows / bind_cols可以抛出以下内容: “错误:行数不兼容(3,期望2)”
我有重复的列名,所以'merge'也不能用于我的目的 - 由于某种原因返回一个空的df。
答案 0 :(得分:4)
好像你可以在rownames上合并,然后将NA
的总和和转换为零,并进行一些额外的修改:
library(dplyr)
df.new = df1 %>% add_rownames %>%
full_join(df2 %>% add_rownames, by="rowname") %>%
mutate_each(funs(replace(., which(is.na(.)), 0))) %>%
mutate(x = x.x + x.y) %>%
select(rowname,x,y,z,w)
或者,@ DavidArenburg提供了更加优雅和可扩展的解决方案:
df.new = df1 %>% add_rownames %>%
full_join(df2 %>% add_rownames) %>%
group_by(rowname) %>%
summarise_each(funs(sum(., na.rm = TRUE)))
df.new
rowname x y z w
1 a 8 4 9 2
2 b 2 5 0 0
3 c 3 6 0 0
4 d 8 0 10 3
答案 1 :(得分:3)
这看起来像普通列名(+行名)上的某种类型的简单合并然后是一个简单的聚合,这就是我要解决的问题
library(data.table)
merge(setDT(df1, keep.rownames = TRUE), # Convert to data.table + keep rows
setDT(df2, keep.rownames = TRUE), # Convert to data.table + keep rows
by = intersect(names(df1), names(df2)), # merge on common column names
all = TRUE)[, lapply(.SD, sum, na.rm = TRUE), by = rn] # Sum all columns by group
# rn x y z w
# 1: a 8 4 9 2
# 2: b 2 5 0 0
# 3: c 3 6 0 0
# 4: d 8 0 10 3
是一个非常直接的基础R解决方案
df1$rn <- row.names(df1)
df2$rn <- row.names(df2)
res <- merge(df1, df2, all = TRUE)
rowsum(res[setdiff(names(res), "rn")], res[, "rn"], na.rm = TRUE)
# x y z w
# a 8 4 9 2
# b 2 5 0 0
# c 3 6 0 0
# d 8 0 10 3
答案 2 :(得分:2)
首先,我会获取新实体的所有行和列的名称:
(all.rows <- unique(c(row.names(df1), row.names(df2))))
# [1] "a" "b" "c" "d"
(all.cols <- unique(c(names(df1), names(df2))))
# [1] "x" "y" "z" "w"
然后我将构造一个包含行和列名称的输出矩阵(矩阵数据初始化为全0),将df1
和df2
添加到该矩阵的相关部分。
out <- matrix(0, nrow=length(all.rows), ncol=length(all.cols))
rownames(out) <- all.rows
colnames(out) <- all.cols
out[row.names(df1),names(df1)] <- unlist(df1)
out[row.names(df2),names(df2)] <- out[row.names(df2),names(df2)] + unlist(df2)
out
# x y z w
# a 8 4 9 2
# b 2 5 0 0
# c 3 6 0 0
# d 8 0 10 3
答案 3 :(得分:1)
在融合/堆叠数据框上使用xtabs
:
out <- rbind(cbind(rn=rownames(df1),stack(df1)), cbind(rn=rownames(df2),stack(df2)))
as.data.frame.matrix(xtabs(values ~ rn + ind, data=out))
# x y w z
#a 8 4 2 9
#b 2 5 0 0
#c 3 6 0 0
#d 8 0 3 10
答案 4 :(得分:0)
我不相信接受(或替代合并)方法是最好的。如果你有共同的行,它会得到不正确的结果,它们会加入而不是求和。
这可以通过将df2更改为:
来琐碎地显示df2 = data.frame(x = c(1,2), y = c(4,5), z = c(9,10), w = c(2, 3))
rownames(df2) = c("a", "d")
预期结果:
rn x y z w
1: a 2 8 9 2
2: b 2 5 0 0
3: c 3 6 0 0
4: d 2 5 10 3
实际结果
merge(setDT(df1, keep.rownames = TRUE),
setDT(df2, keep.rownames = TRUE),
by = intersect(names(df1), names(df2)),
all = TRUE)[, lapply(.SD, sum, na.rm = TRUE), by = rn]
rn x y z w
1: a 1 4 9 2
2: b 2 5 0 0
3: c 3 6 0 0
4: d 2 5 10 3
您需要将外部联接与内部联接(或左/右联接,合并all = T / all = F)组合在一起。或者使用plyr的rbind.fill:
基础R解决方案
res <- rbind.fill(df1,df2)
rowsum(res[setdiff(names(res), "rn")], res[, "rn"], na.rm = TRUE)
数据表解决方案
as.data.table(rbind.fill(
setDT(df1, keep.rownames = TRUE),
setDT(df2, keep.rownames = TRUE)
))[, lapply(.SD, sum, na.rm = TRUE), by = rn]
我更喜欢rbind.fill方法,因为你可以“合并”&gt;使用相同语法的2个数据帧。