#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.42. Я использую версию 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.