В R, как вы обобщаете вычисление совокупной суммы по разным полям матрицы в многомерный массив?
Например, учитывая матрицу
a2 <- array(1:6, dim = c(2,3))
[,1] [,2] [,3] [1,] 1 3 5 [2,] 2 4 6
Совокупная сумма по разным полям может быть рассчитана с помощью apply
:
apply(a2, 2, cumsum)
[,1] [,2] [,3] [1,] 1 3 5 [2,] 3 7 11
t(apply(a2, 1, cumsum))
[,1] [,2] [,3] [1,] 1 4 9 [2,] 2 6 12
Обратите внимание, что в последнем случае требуется некоторое изменение формы. Теперь вопрос:
Как бы вы рассчитали кумулятивные суммы для многомерного массива?
Например, для трехмерного массива, такого как:
a3 <- array(1:24, dim = c(2,3,4))
Меня интересует накопленная сумма по строкам, столбцам и третьему измерению, сохраняющая структуру исходного массива. В частности, совокупная сумма строки должна быть:
, , 1 [,1] [,2] [,3] [1,] 1 4 9 [2,] 2 6 12 , , 2 [,1] [,2] [,3] [1,] 7 16 27 [2,] 8 18 30 , , 3 [,1] [,2] [,3] [1,] 13 28 45 [2,] 14 30 48 , , 4 [,1] [,2] [,3] [1,] 19 40 63 [2,] 20 42 66
Каков будет ответ для n-мерного массива?
4 ответа
Экстраполирование от @G. В ответе Гротендика эта функция использует aperm
для вычисления кумулятивной суммы по любому полю n-мерного массива:
array_cumsum <- function(a, margin) {
n <- length(dim(a))
permorder <- append(x = 2:n, 1, margin - 1)
aperm(apply(a, -margin, cumsum), permorder)
}
Например, используя простой массив, состоящий из единиц, для простоты просмотра кумулятивных сумм, функция может использоваться для вычисления запаса по 2-му измерению:
a <- array(1, dim = c(2,3,4))
array_cumsum(a3, 2)
# , , 1
#
# [,1] [,2] [,3]
# [1,] 1 2 3
# [2,] 1 2 3
#
# , , 2
#
# [,1] [,2] [,3]
# [1,] 1 2 3
# [2,] 1 2 3
#
# , , 3
#
# [,1] [,2] [,3]
# [1,] 1 2 3
# [2,] 1 2 3
#
# , , 4
#
# [,1] [,2] [,3]
# [1,] 1 2 3
# [2,] 1 2 3
А также над 3-м измерением:
array_cumsum(a3, 3)
# , , 1
#
# [,1] [,2] [,3]
# [1,] 1 1 1
# [2,] 1 1 1
#
# , , 2
#
# [,1] [,2] [,3]
# [1,] 2 2 2
# [2,] 2 2 2
#
# , , 3
#
# [,1] [,2] [,3]
# [1,] 3 3 3
# [2,] 3 3 3
#
# , , 4
#
# [,1] [,2] [,3]
# [1,] 4 4 4
# [2,] 4 4 4
Одним из способов является использование старого доброго цикла for
res <- a3
for (k in 1:dim(a3)[3]) res[, , k] <- t(apply(a3[, , k], 1, cumsum))
res
#, , 1
#
# [,1] [,2] [,3]
#[1,] 1 4 9
#[2,] 2 6 12
#
#, , 2
#
# [,1] [,2] [,3]
#[1,] 7 16 27
#[2,] 8 18 30
#
#, , 3
#
# [,1] [,2] [,3]
#[1,] 13 28 45
#[2,] 14 30 48
#
#, , 4
#
# [,1] [,2] [,3]
#[1,] 19 40 63
#[2,] 20 42 66
Это почти дает то, что вы хотите, но результат транспонирован
apply(a3, c(1, 3), cumsum)
#, , 1
# [,1] [,2]
#[1,] 1 2
#[2,] 4 6
#[3,] 9 12
#, , 2
# [,1] [,2]
#[1,] 7 8
#[2,] 16 18
#[3,] 27 30
#, , 3
# [,1] [,2]
#[1,] 13 14
#[2,] 28 30
#[3,] 45 48
#, , 4
# [,1] [,2]
#[1,] 19 20
#[2,] 40 42
#[3,] 63 66
Я не знаю, как мы можем перенести результат в один и тот же вызов apply
(должен быть способ). Я старался
t(apply(a3, c(1, 3), cumsum))
apply(a3, c(1, 3), function(x) t(cumsum(x)))
Но это не работает Однако сейчас, если мы снова используем apply
и транспонируем, мы можем вернуть исходную структуру.
apply(apply(a3, c(1, 3), cumsum), c(1, 3), t)
Используйте apply
, а затем aperm
. Единственная сложность - правильно определить размер полей:
aperm(apply(a3, -2, cumsum), c(2, 1, 3))
Каждый из них также работает:
aperm(apply(a3, c(1, 3), cumsum), c(2, 1, 3))
aperm(apply(a3, c(3, 1), cumsum), c(3, 1, 2))
apply(apply(a3, -2, cumsum), -2, c)
apply(apply(a3, c(1, 3), cumsum), c(1, 3), c)
library(plyr)
aa <- aperm(aaply(a3, c(1, 3), cumsum), c(1, 3, 2))
dimnames(aa) <- NULL
Похожие вопросы
Новые вопросы
arrays
Массив - это упорядоченная линейная структура данных, состоящая из набора элементов (значений, переменных или ссылок), каждый из которых идентифицируется одним или несколькими индексами. Когда вы спрашиваете о конкретных вариантах массивов, используйте вместо них следующие связанные теги: [vector], [arraylist], [matrix]. При использовании этого тега в вопросе, относящемся к языку программирования, пометьте вопрос используемым языком программирования.