Добавить матрицу ко всем фрагментам в массиве

#r

#r

Вопрос:

Это кажется очень простым вопросом R, но возникли некоторые трудности с добавлением матрицы ко всем фрагментам в массиве (на самом деле это стек изображений, и, прежде чем кто-нибудь спросит, есть причина, по которой я хочу сделать это в R). В качестве примера я хочу добавить значение выборки матрицы ко всем фрагментам в третьем измерении combinedAtten:

 combinedAtten <- array(rexp(300), dim = c(10, 10, 3))
sampleMean <- matrix(rep(1:2, 50), ncol = 10)
distortedMask <- apply(combinedAtten, 3, function(x)x   sampleMean)
dim(distortedMask)
 

Неожиданно на выходе получается матрица с уменьшениями [100, 3], а не массив с уменьшениями [10, 10, 3]. У меня есть неуклюжее решение использовать simplify = F, а затем объединить список обратно в массив следующим образом:

 distortedMask <- apply(combinedAtten, 3, function(x)x   sampleMean, simplify = F)
distortedMask <- array(unlist(distortedMask), dim = dim(combinedAtten))
dim(distortedMask)
 

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

Комментарии:

1. apply Получил simplify аргумент в последней версии R. I не существует в версии 4.0.4

2. Я использую версию 4.1.0. Мне никогда не приходило в голову, что упрощение может быть новым дополнением.

3. да @IRTFM, новая функция R 4.1.0

Ответ №1:

Опция replicate ‘sampleMean’, чтобы сделать размеры одинаковыми и добавить ( )

 distoredMask <- combinedAtten   replicate(dim(combinedAtten)[3], sampleMean)
 

ПРИМЕЧАНИЕ: По умолчанию replicate используется simplify = "array"

-проверьте dim

 > all.equal(dim(combinedAtten), dim(distoredMask))
[1] TRUE
 

Или, если мы хотим использовать метод OP, тогда другим вариантом является перенос с simplify2array помощью на list выходе

 distoredMask2 <- simplify2array(apply(combinedAtten, 3,
     function(x)x   sampleMean, simplify = FALSE))
 

-проверка

 > dim(distoredMask2)
[1] 10 10  3
> identical(distoredMask, distoredMask2)
[1] TRUE
 

Ответ №2:

Редактировать: Теперь, когда я понимаю, какова была цель, я могу предположить, что все, что вам нужно было сделать, это изменить размер полученного вами результата, который был равен 100 x 3

 dim(distortedMask) <- c(10,10,3)
dim(distortedMask)
#[1] 10 10  3
 

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

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


Предыдущее предложение нецелевое:

 identical(distortedMask, combinedAtten   c(sampleMean,sampleMean,sampleMean) )
[1] TRUE
 


Посмотрите, есть ли abind в пакете abind то, что вы хотите:

 > library(abind)
> str(abind(combinedAtten,sampleMean))
 num [1:10, 1:10, 1:4] 0.862 0.639 0.3 0.193 0.259 ...
 - attr(*, "dimnames")=List of 3
  ..$ : NULL
  ..$ : NULL
  ..$ : NULL
 

Это похоже на то, что, я думаю, вы хотели, так что попробуйте:

  distortedMask <- abind(combinedAtten,sampleMean) # after library(abind)
 

Комментарии:

1. Не делает того, что я искал, но abind — полезное предложение для rbind / cbind для массивов.

2. @Knackiedoo Итак, все, что вы хотели сделать, это изменить атрибут измерения?

3. Переопределение выходных данных с помощью dim( ) < — это интересный маленький трюк, который нужно запомнить, спасибо. 1.