R-每n个元素的快速行和矩阵
我有一个问题,关于每个第n个元素行的快速求和 考虑一个16列m行的矩阵。结果应该有4列和m行,其中每列是每n个元素的和,即第一列是第1、5、9、13列的和,第二列是第2、6、10、14列的和 目前我通过矩阵乘法来实现这一点。但是,对于大型矩阵,这需要花费太长的时间。发布的解决方案仅对一行中的n个连续元素求和,而不是拆分 /编辑: 以下是我目前解决问题的方法:R-每n个元素的快速行和矩阵,r,matrix,R,Matrix,我有一个问题,关于每个第n个元素行的快速求和 考虑一个16列m行的矩阵。结果应该有4列和m行,其中每列是每n个元素的和,即第一列是第1、5、9、13列的和,第二列是第2、6、10、14列的和 目前我通过矩阵乘法来实现这一点。但是,对于大型矩阵,这需要花费太长的时间。发布的解决方案仅对一行中的n个连续元素求和,而不是拆分 /编辑: 以下是我目前解决问题的方法: test <- matrix(c(1:24000),ncol=64) SumFeatures <- function(nco
test <- matrix(c(1:24000),ncol=64)
SumFeatures <- function(ncol,nthElement) {
ncolRes <- ncol/nthElement
matrix(c(rep(diag(ncolRes),times = nthElement)),ncol = ncolRes,byrow = TRUE)
}
# Get Matrix to sum over every 4th element
sumMatrix <- SumFeatures(ncol(test),4)
system.time(test %*% sumMatrix)
test使用从内置11×8数据框导出的矩阵m
作为输入anscombe
:
# create test matrix m
m <- as.matrix(anscombe)
给予:
1 2 3 4
[1,] 18.04 19.14 17.46 14.58
[2,] 14.95 16.14 14.77 13.76
[3,] 20.58 21.74 25.74 15.71
[4,] 17.81 17.77 16.11 16.84
[5,] 19.33 20.26 18.81 16.47
[6,] 23.96 22.10 22.84 15.04
[7,] 13.24 12.13 12.08 13.25
[8,] 8.26 7.10 9.39 31.50
[9,] 22.84 21.13 20.15 13.56
[10,] 11.82 14.26 13.42 15.91
[11,] 10.68 9.74 10.73 14.89
test replications elapsed relative
6 six 1000 0.12 1.000
5 five 1000 0.18 1.500
4 four 1000 0.30 2.500
2 two 1000 0.31 2.583
3 three 1000 0.39 3.250
7 seven 1000 0.58 4.833
1 one 1000 2.27 18.917
2)t轻轻地或这会给出相同的结果:
do.call(cbind, tapply(1:ncol(m), gl(4, 1, ncol(m)), function(ix) rowSums(m[, ix])))
3)tapply-2或给出类似结果的:
matrix(tapply(m, gl(4 * nrow(m), 1, length(m)), sum), nrow(m))
4)应用/array或此操作,这还要求将相同数量的输入列汇总到每个输出列中:
apply(array(m, c(nrow(m), 4, ncol(m) / 4)), 1:2, sum)
注意,在m
的情况下,这只是apply(数组(m,c(11,4,2),1:2,sum)
5)对于此备选方案基于
for循环:
res <- 0
for(i in seq(1, ncol(m), 4)) res <- res + m[, seq(i, length = 4)]
res
7)行和
t(rowsum(t(m), gl(4, 1, ncol(m))))
注意:以下测试的解决方案
- (6) ,(5)和(4)按速度降序排列最快(即(6)最快)。这三个参数还要求
的列数为4的偶数倍。(2) 是不需要偶数倍数的解决方案中最快的,然后是(3)、(7)和(1),其中(1)是最慢的m
- (7) 是最短的,(1)是次短的,(4)是第三短的
library(rbenchmark)
benchmark(
one = t(apply(m, 1, tapply, gl(4, 1, ncol(m)), sum)),
two = do.call(cbind,
tapply(1:ncol(m), gl(4, 1, ncol(m)), function(ix) rowSums(m[, ix]))),
three = matrix(tapply(m, gl(4 * nrow(m), 1, length(m)), sum), nrow(m)),
four = apply(array(m, c(nrow(m), 4, ncol(m) / 4)), 1:2, sum),
five = {res <- 0
for(i in seq(1, ncol(m), 4)) res <- res + m[, seq(i, length = 4)]
res },
six = matrix(Reduce("+", split(m, gl(ncol(m) / 4, nrow(m) * 4))), nrow(m)),
seven = t(rowsum(t(m), gl(4, 1, ncol(m)))),
order = "relative", replications = 1000)[1:4]
根据我的经验,如果将问题简化为内存中相邻的两个一维数组之间的操作,则可以获得绝对最快的计算速度。这通常涉及到重塑数据,这可能是一项昂贵的操作,但如果您需要重复多次计算,这是值得的 以11×8矩阵为例(与G.Grothendieck的解决方案相同),我会这样做
dim(m) <- c(44, 2)
out <- m[, 1] + m[, 2]
dim(out) <- c(11, 4)
dim(m)您能提供一些数据以便我们可以帮助您吗?请参见此处,了解可重复性最低的示例:
test replications elapsed relative
6 six 1000 0.12 1.000
5 five 1000 0.18 1.500
4 four 1000 0.30 2.500
2 two 1000 0.31 2.583
3 three 1000 0.39 3.250
7 seven 1000 0.58 4.833
1 one 1000 2.27 18.917
dim(m) <- c(44, 2)
out <- m[, 1] + m[, 2]
dim(out) <- c(11, 4)