Convert vector to array index in R?

自作多情 提交于 2021-02-08 07:39:39

问题


Say that we have an array A, that has arbitrary dimension dim(A). Say that we have a coordinate index vector V. Is there any way to access the element of A with coordinates V? Doing something like A[V] doesn't work obviously. If V=c(1,2,3) then A[V] will just give us the 1st, 2nd, and 3rd element of A. What if we want A[1,2,3] instead? If we know dim(A) ahead of time, this is easy obviously. But what if we want to make code that works no matter how many dimensions A has?


回答1:


We may use do.call to execute `[`.

v <- c(1, 2, 3)

do.call(`[`, c(list(A), v))
# [1] 22

To assign we have `[<-`.

A <- do.call(`[<-`, c(list(A), v, 99))

Check:

A[,,3]
# , , 3
# 
# [,1] [,2] [,3]
# [1,]   19   99   25
# [2,]   20   23   26
# [3,]   21   24   27

Using @duckmayr's A

A <- array(1:(3^3), dim = c(3, 3, 3))



回答2:


You can make use of eval(parse()), like so:

foo <- function(A, v) {
    stopifnot(length(v) == length(dim(A)))
    idx <- paste(v, collapse = ", ")
    return(eval(parse(text = paste0("A[", idx, "]"))))
}

A <- array(1:(3^3), dim = c(3, 3, 3))
v <- c(1, 2, 3)

foo(A, v)
# [1] 22
A[1, 2, 3]
# [1] 22

Update: Assignment

In the comments you also ask about assignment; it looks like you've got it sorted, but in case you or someone else finds it useful, you could use a replacement function:

`foo<-` <- function(A, v, value) {
    stopifnot(length(v) == length(dim(A)))
    stopifnot(is.atomic(value) & length(value) == 1)
    idx <- paste(v, collapse = ", ")
    eval(parse(text = paste0("A[", idx, "] <- value")))
    return(A)
}

foo(A, v) <- 2
foo(A, v)
# [1] 2


来源:https://stackoverflow.com/questions/61800479/convert-vector-to-array-index-in-r

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!