我有一个数据框,其中一些连续的列具有相同的名称。我需要搜索这些,为每行添加它们的值,删除一列并用它们的总和替换另一列。 之前不知道哪些模式是重复的,可能需要将一个列名与下面的名称进行比较,以确定是否匹配。
有人可以帮忙吗?
提前致谢。
答案 0 :(得分:7)
> dfrm <- data.frame(a = 1:10, b= 1:10, cc= 1:10, dd=1:10, ee=1:10)
> names(dfrm) <- c("a", "a", "b", "b", "b")
> sapply(unique(names(dfrm)[duplicated(names(dfrm))]),
function(x) Reduce("+", dfrm[ , grep(x, names(dfrm))]) )
a b
[1,] 2 3
[2,] 4 6
[3,] 6 9
[4,] 8 12
[5,] 10 15
[6,] 12 18
[7,] 14 21
[8,] 16 24
[9,] 18 27
[10,] 20 30
编辑2:使用rowSums允许将第一个sapply参数简化为unique(names(dfrm))
,代价是需要记住在“[”中包含drop = FALSE:
sapply(unique(names(dfrm)),
function(x) rowSums( dfrm[ , grep(x, names(dfrm)), drop=FALSE]) )
处理NA的问题:
sapply(unique(names(dfrm)),
function(x) apply(dfrm[grep(x, names(dfrm))], 1,
function(y) if ( all(is.na(y)) ) {NA} else { sum(y, na.rm=TRUE) }
) )
(编辑注释:通过在名称(。)[。]构造周围添加唯一性来解决Tommy反例。 错误的代码是:
sapply(names(dfrm)[unique(duplicated(names(dfrm)))],
function(x) Reduce("+", dfrm[ , grep(x, names(dfrm))]) )
答案 1 :(得分:4)
这是我的一个班轮
# transpose data frame, sum by group = rowname, transpose back.
t(rowsum(t(dfrm), group = rownames(t(dfrm))))
答案 2 :(得分:2)
一些示例数据。
dfr <- data.frame(
foo = rnorm(20),
bar = 1:20,
bar = runif(20),
check.names = FALSE
)
方法:循环唯一的列名称;如果只有一个名称,那么用该nme选择所有列将返回一个向量,但如果有重复,它也将是一个数据帧。使用rowSums
对行进行求和。 ( Duh。编辑:不像以前想的那样'duh'!) 编辑:lapply
返回一个列表,我们需要将其改造成数据框,最后我们修复了名称。sapply
避免了最后一步的需要。
unique_col_names <- unique(colnames(dfr))
new_dfr <- sapply(unique_col_names, function(name)
{
subs <- dfr[, colnames(dfr) == name]
if(is.data.frame(subs))
rowSums(subs)
else
subs
})
答案 3 :(得分:1)
一种方法是使用(惊讶)duplicated
函数识别重复项,然后循环遍历它们以计算总和。这是一个例子:
dat.dup <- data.frame(x=1:10, x=1:10, x=1:10, y=1:10, y=1:10, z=1:10, check.names=FALSE)
dups <- unique(names(dat.dup)[duplicated(names(dat.dup))])
for (i in dups) {
dat.dup[[i]] <- rowSums(dat.dup[names(dat.dup) == i])
}
dat <- dat.dup[!duplicated(names(dat.dup))]