有没有办法动态访问数组维度(理想情况下无需重塑)?我有一个 n 维数组arr
以及一个命名的维度顺序vals
。的维度数量arr
和的顺序都vals
可能发生变化。我总是想访问等于arr
的维度的第一个条目。在下面我提供了三个例子来说明我想要什么:vals
B
#Example 1
vals = c("A","B","C")
idx = grep("B",vals)
arr = array(runif(5^3), dim = c(5,5,5))
arr[,1,] # B is in second dimension
#Example 2
vals = c("A","C","B","D")
idx = grep("B",vals)
arr = array(runif(5^4), dim = c(5,5,5,5))
arr[,,1,] #B is in third dimension
#Example 3
vals = c("B","A","C","D","E")
idx = grep("B",vals)
arr = array(runif(5^5), dim = c(5,5,5,5,5))
arr[1,,,,] #B is in first dimension
我根本不知道该如何处理这个问题。
1
5 个回答
5
我认为最简单、最有效的方法是使用asplit
asplit(arr, idx)[[1]]
其他选择
您也可以尝试apply
以下方法
array(apply(arr, idx, c)[, 1], dim(arr)[-idx])
并验证它,例如
> set.seed(0)
> vals <- c("B", "A", "C", "D", "E")
> idx <- grep("B", vals)
> arr <- array(runif(5^5), dim = c(5, 5, 5, 5, 5))
> a <- arr[1, , , , ] # B is in first dimension
> b <- array(apply(arr, idx, c)[, 1], dim(arr)[-idx])
> all.equal(a, b)
[1] TRUE
如果你对它的索引逻辑感到困扰apply
,你可以像这样解析字符串
b <- eval(str2lang(sprintf("arr[%s]", toString(replace(rep("", length(dim(arr))), idx, "1")))))
你可以获得
> all.equal(a, b)
[1] TRUE
1
-
asplit
非常简洁,但eval
这里的解决方案似乎运行得更快。
–
|
像这样(使用vals
并arr
来自你的例子)?
the_letter <- 'B'
picklist <- Map(vals, f = \(val) ifelse(val == the_letter, 1, TRUE))
do.call(`[`, c(list(x = arr), picklist))
|
您可以创建一个文本并对其进行评估:例如
cmd <- sprintf("arr[%s]", paste(ifelse(vals == "B", "1", ""), collapse = ","))
cmd
[1] "arr[,1,]"
eval(parse(text = cmd))
1
-
啊,谢谢!我
eval()
以前试过,但我认为我用错了(没有这个parse()
功能)。
–
|
和do.call
:
do.call(`[`, c(list(arr), replace(as.list(rep(TRUE, length(dim(arr)))),
grep("B", vals), 1)))
#Example 1
vals = c("A","B","C")
idx = grep("B",vals)
arr = array(runif(5^3), dim = c(5,5,5))
identical(
do.call(`[`, c(list(arr), replace(as.list(rep(TRUE, length(dim(arr)))),
grep("B", vals), 1))),
arr[,1,] # B is in second dimension
)
#> [1] TRUE
#Example 2
vals = c("A","C","B","D")
idx = grep("B",vals)
arr = array(runif(5^4), dim = c(5,5,5,5))
identical(
do.call(`[`, c(list(arr), replace(as.list(rep(TRUE, length(dim(arr)))),
grep("B", vals), 1))),
arr[,,1,] #B is in third dimension
)
#> [1] TRUE
#Example 3
vals = c("B","A","C","D","E")
idx = grep("B",vals)
arr = array(runif(5^5), dim = c(5,5,5,5,5))
identical(
do.call(`[`, c(list(arr), replace(as.list(rep(TRUE, length(dim(arr)))),
grep("B", vals), 1))),
arr[1,,,,] #B is in first dimension
)
#> [1] TRUE
|
apply
对不对应于 B 的索引使用每个索引中的第一个。这很简洁,并且确实涉及显式重塑。
apply(arr, which(vals != "B"), head, 1)
测试
set.seed(123)
vals = c("A","B","C")
arr = array(runif(5^3), dim = c(5,5,5))
identical(apply(arr, which(vals != "B"), head, 1), arr[,1,])
## [1] TRUE
set.seed(123)
vals = c("A","C","B","D")
arr = array(runif(5^4), dim = c(5,5,5,5))
identical(apply(arr, which(vals != "B"), head, 1), arr[,,1,])
## [1] TRUE
set.seed(123)
vals = c("B","A","C","D","E")
arr = array(runif(5^5), dim = c(5,5,5,5,5))
identical(apply(arr, which(vals != "B"), head, 1), arr[1,,,,])
## [1] TRUE
|
–
|