【发布时间】:2021-08-27 12:22:30
【问题描述】:
假设我有以下代码
u <- c(1,2,3,4,5,6)
l <- c()
for (i in j) {
l[i] <- u[i]+u[i+1]
}
我想创建一个 for 循环,以便获得以下三个值:u[1]+u[2] 和 u[3]+u[4],最后是 u[5]+u[6 ].
【问题讨论】:
假设我有以下代码
u <- c(1,2,3,4,5,6)
l <- c()
for (i in j) {
l[i] <- u[i]+u[i+1]
}
我想创建一个 for 循环,以便获得以下三个值:u[1]+u[2] 和 u[3]+u[4],最后是 u[5]+u[6 ].
【问题讨论】:
不需要for循环,你可以这样做:
tapply(u, ceiling(seq_along(u)/2), sum)
1 2 3
3 7 11
【讨论】:
for (i in 1:length(u)) {
if(i %% 2 ==0){
print(u[i] + u[i-1])
}
}
i %% 2 == 0 表示 i 是偶数。
结果
[1] 3
[1] 7
[1] 11
【讨论】:
我建议如下,因为它很生动:
通过2 创建一个length(u) 矩阵并对行求和
rowSums(matrix(u, ncol = 2, byrow = TRUE))
这也应该是一个非常快速的解决方案,因为您可以在R 中使用大规模矢量化。例如
u <- c(1,2,3,4,5,6)
microbenchmark::microbenchmark(rowSums(matrix(u,ncol=2,byrow = TRUE)),
tapply(u, ceiling(seq_along(u)/2), sum))
在我的机器上提供以下基准:
Unit: microseconds
expr min lq mean median uq max neval
rowSums(matrix(u, ncol = 2, byrow = TRUE)) 4.3 4.80 6.920 6.50 7.3 27.1 100
tapply(u, ceiling(seq_along(u)/2), sum) 77.5 83.45 89.378 85.25 87.8 206.4 100
将u 扩展到10000 个元素,tapply-解决方案变得非常慢,请参阅
u <- rnorm(1:1e4)
microbenchmark::microbenchmark(rowSums(matrix(u,ncol=2,byrow = TRUE)),
tapply(u, ceiling(seq_along(u)/2), sum))
Unit: microseconds
expr min lq mean median uq max neval
rowSums(matrix(u, ncol = 2, byrow = TRUE)) 49.1 57.45 71.145 67.25 73.50 166.4 100
tapply(u, ceiling(seq_along(u)/2), sum) 17995.5 19488.75 20653.714 20388.00 21223.55 34126.6 100
更新:您甚至可以使用colSums(matrix(u, nrow = 2)) 挤出更多内容,因为这样您就可以在R 中使用默认的byrow=FALSE-matrix-construction(也会减少代码):
u <- 1:1e5
microbenchmark::microbenchmark(rowSums(matrix(u, ncol = 2, byrow = TRUE)),
colSums(matrix(u, nrow = 2)))
Unit: microseconds
expr min lq mean median uq max neval
rowSums(matrix(u, ncol = 2, byrow = TRUE)) 767.5 812.65 916.154 851.95 948.25 1669.4 100
colSums(matrix(u, nrow = 2)) 217.0 232.90 263.355 240.00 272.45 469.8 100
【讨论】: