R - как получить значение многомерного массива вектором индексов
Скажем, у меня есть многомерный массив с именем pi
, и его количество измерений неизвестно до времени выполнения:
dims <- rep(3, dim_count)
pi <- array(0, dims)
Как вы можете видеть, размерность зависит от dim_count
. Как получить значение из массива, когда у меня есть вектор индексов? Например, когда у меня есть:
dim_count <- 5
indexes <- c(1, 2, 3, 3, 3)
Я хочу получить
pi[1, 2, 3, 3, 3]
Есть ли короткий, эффективный и, надеюсь, элегантный способ сделать это?
Ответы
Ответ 1
Использование малоизвестного использования [
:
При индексировании массивов на [
один аргумент i
может быть матрицей с таким количеством столбцов, как размеры x
; результатом является вектор с элементами, соответствующими наборам индексов в каждой строке i
.
вы можете просто:
pi[matrix(indexes, 1)]
Ответ 2
do.call("[",...)
, похоже, работает.
indexes <- c(1,2,3,3,3)
pi[1,2,3,3,3] <- 17 ## so we know if we succeeded or not
do.call("[",c(list(pi),as.list(indexes)))
Обратите внимание, что ваш пример не будет работать - ваши измерения были все 3, но некоторые из ваших индексных элементов были > 3...
Ответ 3
do.call()
- это вариант:
dim_count <- 5
indexes <- c(1, 2, 2, 2, 3)
dims <- rep(3, dim_count)
pi <- array(seq_len(prod(dims)), dims)
do.call(`[`, c(list(x = pi), as.list(indexes)))
Что дает:
> do.call(`[`, c(list(x = pi), as.list(indexes)))
[1] 202
> pi[1, 2, 2, 2, 3]
[1] 202
Трудный бит получает список аргументов в правильном формате. pi
должен быть первым аргументом "["
(или назван как аргумент x
, см. ?"["
), в то время как мы хотим, чтобы каждый элемент indexes
сам являлся компонентом поставляемого списка, а не вектором внутри этот список. Следовательно, свернутый c(list(x = pi), as.list(indexes))
.
Альтернативным способом построения списка аргументов, который может быть проще, является следующее:
ARGS <- vector("list", length = dim_count + 1)
ARGS[[1]] <- pi
ARGS[2:length(ARGS)] <- indexes
do.call("[", ARGS)
который дает
> do.call("[", ARGS)
[1] 202
> pi[1, 2, 2, 2, 3]
[1] 202