rollapply для многомерных массивов (R)

Не является дубликатом rollapply для двумерных массивов (R) , а скорее его разработка - то, что я на самом деле хочу сделать, немного сложнее, чем описано в этом вопросе. Я надеялся, что любой ответ на этот вопрос легко распространится на решение моей актуальной проблемы, но, к сожалению, это не так.

Для простых векторов имеем

> a <- c(1:4)
> a
[1] 1 2 3 4
> rollapply(a, 2, mean)
[1] 1.5 2.5 3.5

что так и должно быть. Хотя сам rollapply ограничен одномерными векторами, несколько очень полезных ответов, таких как этот от akrun, позволили мне расширить это к двумерным массивам множеством способов.

К сожалению, я снова застрял, потому что не вижу, как какой-либо из ответов обобщается на более высокие измерения, чем два (*). Взять массив b

> b <- array(rep(c(1:4),each=6), c(2,3,4))
> b
, , 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

должен быть какой-то способ использовать средства с размером окна 2, чтобы получить

, , 1

     [,1] [,2] [,3]
[1,]  1.5  1.5  1.5
[2,]  1.5  1.5  1.5

, , 2

     [,1] [,2] [,3]
[1,]  2.5  2.5  2.5
[2,]  2.5  2.5  2.5

, , 3

     [,1] [,2] [,3]
[1,]  3.5  3.5  3.5
[2,]  3.5  3.5  3.5

но я не понимаю, как (очевидно, в реальных случаях подмассивы не будут состоять из простого повторения одного и того же целого числа по всему массиву, а будут содержать фактические данные).

В идеале я также хотел бы иметь возможность назначать разные веса различным подмассивам в окне для целей усреднения, но я предполагаю, что это просто вопрос определения пользовательской функции для применения.

(*) Возможно, есть очевидный способ, но я уже поздно и не нахожу его.


person Drubbels    schedule 12.05.2021    source источник
comment
Вам нужно apply(b, c(1,2), FUN = function(x) rollapply(x, 2, FUN = mean))   -  person akrun    schedule 13.05.2021
comment
Я был сбит с толку тем, что это, похоже, не делает то, о чем я прошу, но, похоже, это работает в сочетании с aperm!   -  person Drubbels    schedule 13.05.2021
comment
Спасибо еще раз. К тому же вся эта авантюра привела к тому, что я наконец-то обнаружил aperm. Я знал, что R должен иметь какой-то эквивалент swapaxes NumPy, но пока не смог его найти.   -  person Drubbels    schedule 13.05.2021


Ответы (2)


Я не мог заставить zoo::rollapply работать (в качестве внешнего вызова, в отличие от его внутреннего использования в одном из комментариев), но можно имитировать большую часть его поведения, управляя входным вектором извне (seq_len(dim(b)[3])[-1]) и окном ([-1] извне, и i-1:0 внутри). Оттуда это просто среднее значение одного тусклого массива:

sapply(seq_len(dim(b)[3])[-1],
       function(i) apply(b[,,i-1:0,drop=FALSE], 1:2, mean),
       simplify="array")
# , , 1
#      [,1] [,2] [,3]
# [1,]  1.5  1.5  1.5
# [2,]  1.5  1.5  1.5
# , , 2
#      [,1] [,2] [,3]
# [1,]  2.5  2.5  2.5
# [2,]  2.5  2.5  2.5
# , , 3
#      [,1] [,2] [,3]
# [1,]  3.5  3.5  3.5
# [2,]  3.5  3.5  3.5
person r2evans    schedule 12.05.2021

Проблема с apply заключается в том, что он может выполнять неявное транспонирование размеров, но aaply в пакете plyr аналогично, но без неявного транспонирования.

library(plyr)
library(zoo)

aaply(b, 1:2, rollmean, 2)

давая:

   X2
X1    1   2   3
  1 1.5 1.5 1.5
  2 1.5 1.5 1.5

, ,  = 2

   X2
X1    1   2   3
  1 2.5 2.5 2.5
  2 2.5 2.5 2.5

, ,  = 3

   X2
X1    1   2   3
  1 3.5 3.5 3.5
  2 3.5 3.5 3.5
person G. Grothendieck    schedule 13.05.2021