在矩阵/数据框中对行组进行操作

4
假设我有一个矩阵(可以是可转换为矩阵的数据框,反之亦然)。
X=matrix(rnorm(45), nr=15 )
          [,1]       [,2]        [,3]
 [1,] -0.35659671 -0.5014418 -0.90051481
 [2,] -2.84945987 -0.6558198 -1.59163998
 [3,] -0.03612257  0.7118217 -0.76520379
 [4,]  2.45922337 -1.4965018 -0.28132609
 [5,] -0.46939481 -2.2576689 -0.91045703
 [6,]  0.65121124 -0.4879071 -1.81893484
 [7,] -0.28633954  0.3570085 -2.40230043
 [8,] -1.32283279 -0.4904968  0.42214466
 [9,]  0.55199355 -1.5181311 -0.62465292
[10,] -1.00114458  0.5140162 -0.01261708
[11,] -1.49307374  0.1734213  1.38231439
[12,] -1.71157588 -0.7030724 -1.05475532
[13,]  1.13823870  1.3380262  2.74988880
[14,] -0.41600520 -0.9527629  0.68447386
[15,] -1.25893418 -0.3633260  0.38870010

获取列总和很容易(使用colSumsapply 或者其他喜欢的方法)。但是,我有一个位置索引,比方说


idx=c(3,7,13)

所以我需要将矩阵分割并对子部分的列进行求和(或者一般地执行某些函数),例如对于行1到3、4到7、8到13和14到15(最后一行),并获得4乘3矩阵。

          [,1]       [,2]        [,3]
[1,] -3.2421792 -0.4454399 -3.2573586
[2,]  2.3547000 -3.8850690 -5.4130180
[3,] -3.8383947 -0.6862365  2.8623225
[4,] -1.6749390 -1.3160890  1.0731740

这是一个最小可重现的示例。实际矩阵要大得多,子部分的数量和位置是可变的,并且函数更加复杂 :)


使用Map的方法提供了一个好的一行代码,但是@akrun的第一个解决方案更快。 - Colonel Beauvel
2个回答

5

尝试

 indx <- c(idx[1],diff(c(idx, nrow(X))))
 rownames(X) <- rep(seq_along(indx), indx)
 res <- rowsum(X, group=rownames(X))
 dimnames(res) <- NULL
 res
 #         [,1]       [,2]      [,3]
 #[1,] -3.242179 -0.4454399 -3.257359
 #[2,]  2.354700 -3.8850693 -5.413018
 #[3,] -3.838395 -0.6862366  2.862323
 #[4,] -1.674939 -1.3160889  1.073174

如果我们在更改行名称后将“矩阵”转换为“data.table”,则可以这样做:
 library(data.table)#v1.9.5+
 as.data.table(X, keep.rownames=TRUE)[, lapply(.SD, sum), by=rn]
 #  rn        V1         V2        V3
 #1:  1 -3.242179 -0.4454399 -3.257359
 #2:  2  2.354700 -3.8850693 -5.413018
 #3:  3 -3.838395 -0.6862366  2.862323
 #4:  4 -1.674939 -1.3160889  1.073174

或者在修改“X”中的行名称之前使用dplyr

 library(dplyr)
 as.data.frame(X) %>% 
            group_by(rn=rep(seq_along(indx), indx)) %>%
            summarise_each(funs(sum))
 #rn        V1         V2        V3
 #1  1 -3.242179 -0.4454399 -3.257359
 #2  2  2.354700 -3.8850693 -5.413018
 #3  3 -3.838395 -0.6862366  2.862323
 #4  4 -1.674939 -1.3160889  1.073174

1
您还可以使用Map,然后使用do.callrbind来获取所需的矩阵:
do.call(rbind, Map(function(u,v) colSums(X[u:v,]), c(1, idx+1), c(idx, nrow(X))))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接