arrays - 如何在 R 中重新排序数组的第一个维度(不知道总维度)

标签 arrays r indexing subset

我有一个数组,我需要对其第一个维度进行子集/索引/重新排序。例如:

arr <- array(1:24, dim=c(4,3,2))
arr[4:1,,]

简单,工作起来很有魅力。

但是,当我不确定数组有多少维时,有没有办法做到这一点?要明确的是,我将始终知道第一个维度的大小(即,我知道dim(arr)[1]),我只是不知道length(dim(arr))

最佳答案

这是一个奇怪的选择。这个想法基于我曾经注意到的一个实现怪癖,即 R 似乎将“丢失”的函数参数表示为 symbols具有零长度名称。这如此奇怪的原因之一是 R 通常不允许您创建具有零长度名称的符号:

as.symbol('');
## Error in as.symbol("") : attempt to use zero-length variable name

但是通过一些困惑,我发现你可以通过访问涉及“缺失”参数的表达式的解析树,并索引出包含“缺失”参数的解析树元素来绕过 R 的防御。这是您从这个东西中获得的一些奇怪行为的演示:

substitute(x[]); ## parse tree involving missing argument
## x[]
as.list(substitute(x[])); ## show list representation; third component is the guy
## [[1]]
## `[`
##
## [[2]]
## x
##
## [[3]]
##
##
substitute(x[])[[3]]; ## prints nothing!
##
(function(x) c(typeof(x),mode(x),class(x)))(substitute(x[])[[3]]); ## it's a symbol alright
## [1] "symbol" "name"   "name"
as.character(substitute(x[])[[3]]); ## gets the name of the symbol: the empty string!
## [1] ""
i.dont.exist <- substitute(x[])[[3]]; ## store in variable
i.dont.exist; ## wha??
## Error: argument "i.dont.exist" is missing, with no default

无论如何,这是我们可以针对OP的问题得出的解决方案:

arr <- array(1:24,4:2);
do.call(`[`,c(list(arr,4:1),rep(list(substitute(x[])[[3]]),length(dim(arr))-1)));
## , , 1
##
##      [,1] [,2] [,3]
## [1,]    4    8   12
## [2,]    3    7   11
## [3,]    2    6   10
## [4,]    1    5    9
##
## , , 2
##
##      [,1] [,2] [,3]
## [1,]   16   20   24
## [2,]   15   19   23
## [3,]   14   18   22
## [4,]   13   17   21
##

我希望它能胜过所有其他解决方案,但是@thelatemail,你赢得了这一轮: 啊哈!我意识到我们可以预先计算一个空符号列表(将空符号单独存储在变量中,即不在列表中,是不可用的,如我上面所示)和rep () 解决方案中的列表,而不是在每次调用解决方案时产生 substitute() 解析虚拟表达式的所有开销。看看性能:

straight <- function() arr[4:1,,];
jb <- function() do.call(`[`,c(list(arr,4:1),lapply(dim(arr)[-1],seq_len)));
tlm <- function() do.call(`[`,c(list(arr,4:1),rep(TRUE,length(dim(arr))-1)));
orderD1 <- function(x,ord) { dims <- dim(x); ndim <- length(dims); stopifnot(ndim>0); if (ndim==1) return(x[ord]); wl_i <- which(letters=="i"); dimLetters <- letters[wl_i:(wl_i+ndim-1)]; dimList <- structure(vector("list",ndim),.Names=dimLetters); dimList[[1]] <- ord; for (i in 2:ndim) dimList[[i]] <- 1:dims[i]; do.call("[",c(list(x=x),dimList)); };
rbatt <- function() orderD1(arr,4:1);
bgoldst <- function() do.call(`[`,c(list(arr,4:1),rep(list(substitute(x[])[[3]]),length(dim(arr))-1)));
ls0 <- list(substitute(x[])[[3]]);
ls0;
## [[1]]
##
##
bgoldst2 <- function() do.call(`[`,c(list(arr,4:1),rep(ls0,length(dim(arr))-1)));

microbenchmark(straight(),jb(),tlm(),rbatt(),bgoldst(),bgoldst2(),times=1e5);
## Unit: nanoseconds
##        expr   min    lq      mean median    uq      max neval
##  straight()   428   856  1161.038    856  1284   998142 1e+05
##        jb()  4277  5988  7136.534   6843  7271  1629357 1e+05
##       tlm()  2566  3850  4622.668   4277  4705  1704196 1e+05
##     rbatt() 24804 28226 31975.583  29509 31219 34970873 1e+05
##   bgoldst()  3421  4705  5601.300   5132  5560  1918878 1e+05
##  bgoldst2()  2566  3850  4533.383   4277  4705  1034065 1e+05
<小时/>

刚刚发现有一种更简单的方法来获取空符号,这似乎一直可用:

substitute();
##

我的substitute(x[])[[3]]技巧现在看起来有点愚蠢。

出于好奇,我直接使用 substitute() 对其他解决方案进行了基准测试,与 bgoldst2() 相比,它产生了轻微的性能成本,使其略差于tlm():

bgoldst3 <- function() do.call(`[`,c(list(arr,4:1),rep(list(substitute()),length(dim(arr))-1)));
microbenchmark(straight(),jb(),tlm(),rbatt(),bgoldst(),bgoldst2(),bgoldst3(),times=1e5);
## Unit: nanoseconds
##        expr   min    lq      mean median    uq      max neval
##  straight()   428   856  1069.340    856  1284   850603 1e+05
##        jb()  4277  5988  6916.899   6416  7270  2978180 1e+05
##       tlm()  2566  3849  4307.979   4277  4704  3138122 1e+05
##     rbatt() 24377 28226 30882.666  29508 30364 36768360 1e+05
##   bgoldst()  2994  4704  5165.019   5132  5560  2050171 1e+05
##  bgoldst2()  2566  3849  4232.816   4277  4278  1085813 1e+05
##  bgoldst3()  2566  3850  4545.508   4277  4705  1004131 1e+05

关于arrays - 如何在 R 中重新排序数组的第一个维度(不知道总维度),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32000387/

相关文章:

正则表达式 - 在 : right boundary not escaped 之间抓取

python - 无法通过 Python 中的扭曲将索引从列表“复制”到另一个索引

c - 通过索引访问结构

javascript - postman : How to assert all array elements exist in other array?

PHP MySQL 连接

R:如何在 lapply 函数中获取元素的名称?

r - 为 sf 对象创建距离矩阵

mysql - 多列索引比mysql中的单列索引慢

java - 对数字字符串的 ArrayList 进行排序

java - 在并行数组中查找值 JAVA 初学者