我正在尝试在R中循环移动N维数组。以下是移动2D矩阵pracma
的{{1}}包中的示例:
a
我正在尝试移动一个N维数组,这是我到目前为止所提出的:
if (is.matrix(a) && length(sz) == 2) {
n <- nrow(a); m <- ncol(a)
s1 <- sz[1] %% n
s2 <- sz[2] %% m
a <- a[(1:n-s1-1) %% n + 1, (1:m-s2-1) %% m + 1]
}
我想到的想法是分别循环移动for循环中的每个维度。但我无法弄清楚是否有办法做到这一点,因为矢量/矩阵类型代码(预先给出尺寸)将无法在这种情况下工作......
更具体地说,您必须在语法代码中明确索引每个维度,但如果您不知道维度有多少,这似乎是不可能的。 (或者,更有可能的是,我只是不知道如何)
答案 0 :(得分:2)
您可以使用以下方法执行此操作:
# using map2 from purrr for simplicity, though you could also use lapply
library(purrr)
circshift_any <- function(a, sz) {
indexers <- map2(dim(a), sz, function(len, s) (1:len - s - 1) %% len + 1)
indexing_matrix <- as.matrix(do.call(expand.grid, indexers))
array(a[indexing_matrix], dim(a))
}
这使用了两个技巧:
您可以使用另一个矩阵索引矩阵,而不仅仅是使用逗号分隔的向量(例如,您可以执行as.matrix(mtcars)[cbind(1:3, 2:4)]
。它会将其转换为向量,但您可以将其返回到数组相同的尺寸。
您可以使用expand.grid
创建多个向量的所有组合。通过给它你想要的索引向量,你可以让每一个都适当重复。
通过将其与pracma的输出进行比较,您可以确认这适用于2d矩阵:
a <- array(1:100, c(5, 20))
identical(pracma::circshift(a, c(3, 6)), circshift_any(a, c(3, 6)))
identical(pracma::circshift(a, c(23, 19)), circshift_any(a, c(23, 19)))