高维数组
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
我有一个 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