高维数组

High Dimensional Array

我有一个 13 维数组: MatrixQ<-array(0,dim=c(2,2,2,2,2,2,2,2,2,2,2,2,3))

如何在循环中引用它的第i维?

for (i in 1:13) { 我想将数字 i 分配给数组的第 i 个维度 } 我应该使用什么命令? 谢谢,

据我所知,R 中没有内置的简单方法来执行此操作。但是,您可以利用数组实际上存储为具有维度 (dim) 属性的向量这一事实.因此,您实际上可以直接访问元素而无需使用多个逗号。困难在于计算出底层向量的哪些索引代表您想要的数组切片。这只需要一点数学知识。

我想你正在寻找这样的东西:

at <- function(Array, Dimension, Slice, index = FALSE)
{
  if(!is.array(Array)) 
    stop("'at()' can only be called on arrays")

  if(!(is.numeric(Dimension) && Dimension > 0))
    stop("Invalid value of Dimension supplied to 'at()'")

  # Get the numbers of dimensions and elements in our Array
  n       <- length(Array)
  dims    <- dim(Array)
  n_dims  <- length(dims)

  if(Dimension > n_dims | Dimension < 1) 
    stop("Invalid dimension chosen in 'at()'")

  if(max(Slice) > dims[Dimension]) 
    stop("Invalid slice chosen for given dimension")

  final_result <- numeric()

  for(i in seq_along(Slice))
  {
    run_length  <- cumprod(c(1, dims)[-(n_dims + 1)])[Dimension]
    skip_length <- run_length * (dims[Dimension] - 1)

    # Now we simply make a repeating pattern of membership / non-membership
    pattern         <- rep_len(c(rep(T, run_length), rep(F, skip_length)), n)
    shifted_pattern <- c(rep(FALSE, run_length * (Slice[i] - 1)), pattern)
    loop_result     <- which(shifted_pattern[seq(n)])
    final_result    <- c(final_result, loop_result)
  }
  if(index == FALSE)
  {
    dims[Dimension] <- length(Slice)
    return(array(Array[final_result], dim = dims))
  }
  return(sort(final_result))
}

以下是您的使用方法。从一个数组开始(让我们只有 3 个维度)

my_array <- array(0, dim = c(2, 3, 4))
my_array
#> , , 1
#> 
#>      [,1] [,2] [,3]
#> [1,]    0    0    0
#> [2,]    0    0    0
#> 
#> , , 2
#> 
#>      [,1] [,2] [,3]
#> [1,]    0    0    0
#> [2,]    0    0    0
#> 
#> , , 3
#> 
#>      [,1] [,2] [,3]
#> [1,]    0    0    0
#> [2,]    0    0    0
#> 
#> , , 4
#> 
#>      [,1] [,2] [,3]
#> [1,]    0    0    0
#> [2,]    0    0    0

现在我可以得到表示第三维(即my_array[, , 2])的第二个矩阵的底层数组的索引,如下所示:

at(my_array, 3, 2, index = T)
# [1]  7  8  9 10 11 12

这意味着如果我向 my_array[c(7, 8, 9, 10, 11, 12)] 写入任何内容,它将更改矩阵适当切片中的元素:

my_array[at(my_array, 3, 2, index = T)] <- 69
my_array
#> , , 1
#> 
#>      [,1] [,2] [,3]
#> [1,]    0    0    0
#> [2,]    0    0    0
#> 
#> , , 2
#> 
#>      [,1] [,2] [,3]
#> [1,]   69   69   69
#> [2,]   69   69   69
#> 
#> , , 3
#> 
#>      [,1] [,2] [,3]
#> [1,]    0    0    0
#> [2,]    0    0    0
#> 
#> , , 4
#> 
#>      [,1] [,2] [,3]
#> [1,]    0    0    0
#> [2,]    0    0    0

当然这意味着我们可以做一个循环,我们可以 select 维度。在这里,我们首先将 my_array 重置为零,然后将维度编号放入该维度内第一个切片中的每个元素。请注意,如果某些单元格属于多个维度的第一个切片,则会在此过程中被覆盖。

# Reset my_array first
my_array[] <- 0

for(i in 1:3)
{
  my_array[at(my_array, i, 1, index = T)] <- i;
}
my_array
#> , , 1
#> 
#>      [,1] [,2] [,3]
#> [1,]    3    3    3
#> [2,]    3    3    3
#> 
#> , , 2
#> 
#>      [,1] [,2] [,3]
#> [1,]    2    1    1
#> [2,]    2    0    0
#> 
#> , , 3
#> 
#>      [,1] [,2] [,3]
#> [1,]    2    1    1
#> [2,]    2    0    0
#> 
#> , , 4
#> 
#>      [,1] [,2] [,3]
#> [1,]    2    1    1
#> [2,]    2    0    0

虽然该示例是针对 3 维数组的,但这应该适用于任意数量的维度。

index = T的原因是省略它,我们可以不用索引直接得到我们想要的切片:

at(my_array, 3, 1:2)
#> , , 1
#> 
#>      [,1] [,2] [,3]
#> [1,]    3    3    3
#> [2,]    3    3    3
#> 
#> , , 2
#> 
#>      [,1] [,2] [,3]
#> [1,]    2    1    1
#> [2,]    2    0    0

对于 OP 答案中的示例,您可以使用它来执行以下操作:

Indexlist2 <- numeric()

for(j in 2:4)
{
 if(StartPoint2QQQ[j] == 1)
 {
    j_matches <- which(at(MatrixQQQ, j, 1) == max(at(MatrixQQQ, j, 1)), arr.ind = T)
    Indexlist2 <- rbind(Indexlist2, j_matches)
  }
}

现在我们有

Indexlist2
#>      dim1 dim2 dim3 dim4
#> [1,]    2    2    1    2
#> [2,]    2    2    2    1

MatrixQQQ[Indexlist2]
#> [1] 5.0 0.2
at <- function(array = a, d = 1, slice = 1)
{
  consec <- cumprod(c(1, dim(a)))[-(length(dim(a)) + 1)]
  skip_n <- consec * (dim(a) - 1)
  basic_pattern <- rep_len(c(rep(TRUE, consec[d]), rep(FALSE, skip_n[d])), length(a))
  which(c(rep(FALSE, consec[d] * (slice - 1)), basic_pattern)[seq_along(a)])
}



StartPoint1QQQ <- array(c(1,1,0,0))
StartPoint2QQQ <- array(c(1,1,0,0))+1
MatrixQQQ<-array(0,dim=c(2,2,2,2))
MatrixQQQ[2,2,1,1] <- 0.1
MatrixQQQ[2,2,2,1] <- 0.2
MatrixQQQ[2,2,1,2] <- 5
for(j in 2:4)
{

  if(StartPoint2QQQ[j] == 1)
 {

    Indexlist2 <- which( MatrixQQQ[at(MatrixQQQ, j, 1)] == max( MatrixQQQ[at(MatrixQQQ, j, 1)]), arr.ind = TRUE)
  }
}
#I simplified my higher dimension problem. MatrixQQQ is my 4 dimensional matrix that stores 
#scores for each state (there are 4 states). Here the first state is time, and 2nd-4th states are cost.
#I care for cost only for now, so states 2:4 are of interest. I want to get a list of indices 
# in which the slice is 1 and among them find the ones with maximum MatrixQQQ value

#The expected value here is 2,2,1,2 because its MatrixQQQ value is the highest, 5.
at <- function(Array, Dimension, Slice, index = FALSE)
{
  if(!is.array(Array)) 
    stop("'at()' can only be called on arrays")

  if(!(is.numeric(Dimension) && Dimension > 0))
    stop("Invalid value of Dimension supplied to 'at()'")

  # Get the numbers of dimensions and elements in our Array
  n       <- length(Array)
  dims    <- dim(Array)
  n_dims  <- length(dims)

  if(Dimension > n_dims | Dimension < 1) 
    stop("Invalid dimension chosen in 'at()'")

  if(max(Slice) > dims[Dimension]) 
    stop("Invalid slice chosen for given dimension")

  final_result <- numeric()

  for(i in seq_along(Slice))
  {
    run_length  <- cumprod(c(1, dims)[-(n_dims + 1)])[Dimension]
    skip_length <- run_length * (dims[Dimension] - 1)

    # Now we simply make a repeating pattern of membership / non-membership
    pattern         <- rep_len(c(rep(T, run_length), rep(F, skip_length)), n)
    shifted_pattern <- c(rep(FALSE, run_length * (Slice[i] - 1)), pattern)
    loop_result     <- which(shifted_pattern[seq(n)])
    final_result    <- c(final_result, loop_result)
  }
   if(index == FALSE)
  {
    dims[Dimension] <- length(Slice)
    return(array(Array[final_result], dim = dims))
  }
  return(sort(final_result))
}


IMAX <- 2

MatrixQ<-array(0,dim=c(2,2,2,2,2,2,2,2,2,2,2,2,3))
MatrixQ[2,2,1,1,1,1,1,1,1,2,1,2,IMAX] <- 5000

j <- 10


which(MatrixQ == max(MatrixQ), arr.ind = T)

which(at(MatrixQ, j, 2) == max(at(MatrixQ, j, 2)), arr.ind = T)



######ANSWER I GET:###########################
####which(MatrixQ == max(MatrixQ), arr.ind = T)
####      dim1 dim2 dim3 dim4 dim5 dim6 dim7 dim8 dim9 dim10 dim11 dim12 dim13
####[1,]    2    2    1    1    1    1    1    1    1     2     1     2     2

####> which(at(MatrixQ, j, 2) == max(at(MatrixQ, j, 2)), arr.ind = T)
####       dim1 dim2 dim3 dim4 dim5 dim6 dim7 dim8 dim9 dim10 dim11 dim12 dim13
####[1,]    2    2    1    1    1    1    1    1    1     1     1     2     2