Мнение по умолчанию (я полагаю) в отношении MARGIN=
(второго) аргумента для apply
заключается в том, что оно означает «уменьшенную ось» (при агрегировании ... здесь упрощается для эффекта).Однако, с другой стороны, все остальные измерения остаются неизменными.
Эффективный эквивалент colSums(ary)
, например, равен apply(ary, 2, sum)
, что означает «сохранить ось 1 неизменной».(colSums
фактически выполняется внутренне, а не с apply
.) Итак, чтобы расширить логику «все оси , кроме », давайте осознаем, что для вашей b_array
вы хотите, чтобы 1-я и 3-я оси осталисьТаким образом,
apply(b_array, c(1,3), sum)
# [,1] [,2] [,3]
# [1,] 13.27586 13.27586 13.27586
# [2,] 13.96552 13.96552 13.96552
# [3,] 14.65517 14.65517 14.65517
# [4,] 15.34483 15.34483 15.34483
# [5,] 16.03448 16.03448 16.03448
# [6,] 16.72414 16.72414 16.72414
настолько эффективен, насколько вы можете (я думаю) получить сумму «столбца» с n -мерным массивом.
Edit :
@ markus Использование aperm
быстрее в широком диапазоне размеров матриц, хотя, по-видимому, оно сходится при больших матрицах.
ns <- c(10,50,100,1000)
set.seed(123)
arrays <- lapply(ns, function(n) array(runif(3*n*n), dim=c(n,n,3)))
mapply(identical,
lapply(arrays, function(a) t(colSums(aperm(a, perm = c(2, 3, 1))))),
lapply(arrays, function(a) apply(a, c(1,3), sum)))
# [1] TRUE TRUE TRUE TRUE
library(microbenchmark)
microbenchmark(
aperm10 = t(colSums(aperm(arrays[[1]], perm = c(2, 3, 1)))),
aperm50 = t(colSums(aperm(arrays[[2]], perm = c(2, 3, 1)))),
aperm100 = t(colSums(aperm(arrays[[3]], perm = c(2, 3, 1)))),
aperm1000 = t(colSums(aperm(arrays[[4]], perm = c(2, 3, 1)))),
apply10 = apply(arrays[[1]], c(1,3), sum),
apply50 = apply(arrays[[2]], c(1,3), sum),
apply100 = apply(arrays[[3]], c(1,3), sum),
apply1000 = apply(arrays[[4]], c(1,3), sum),
times=10
)
# Unit: microseconds
# expr min lq mean median uq max neval
# aperm10 19.1 25.5 46.74 39.55 59.2 105.8 10
# aperm50 55.7 77.2 96.36 94.30 115.6 149.8 10
# aperm100 231.2 247.2 267.14 258.35 295.5 301.8 10
# aperm1000 47282.5 47568.4 49235.19 49581.85 50118.4 52034.4 10
# apply10 53.7 59.1 78.42 63.15 105.6 123.5 10
# apply50 263.9 282.3 318.08 306.60 366.4 383.0 10
# apply100 637.7 686.6 712.65 710.75 741.5 799.7 10
# apply1000 40173.7 52735.7 52170.08 54349.65 55692.9 57375.9 10
(Я не проверял использование памяти.)