如何将"nothing"作为参数传递给`[`for subsetting?

Car*_*oft 15 r subset do.call

我希望能够构建do.call子集化的公式,而不必识别输入数组中每个维度的实际范围.我遇到的问题是我无法弄清楚如何模仿直接函数x[,,1:n,],其他维度中没有条目意味着"抓住所有元素".

这是一些示例代码,它失败了.据我所知,[或者do.call用索引替换我的NULL列表值1.

x<-array(1:6,c(2,3))
dimlist<-vector('list', length(dim(x)))
shortdim<-2
dimlist[[shortdim]] <- 1: (dim(x)[shortdim] -1)
flipped <- do.call(`[`,c(list(x),dimlist)) 
Run Code Online (Sandbox Code Playgroud)

我想我可以通过-2*max(dim(x))为每个元素分配值来解决问题dimlist,但是很糟糕.
(FWIW,我有替代功能,可以通过melt/recast或者可怕的"构建一个字符串然后eval(parse(mystring)),但我想要做得更好"来完成所需的工作.")

编辑:作为一个旁边,我运行了这个代码的版本(相当于DWin的TRUE设置)对使用的函数melt & acast; 后者慢几倍,没有真正意外.

Hon*_*Ooi 14

经过一番探讨后,alist似乎可以做到这一点:

x <- matrix(1:6, nrow=3)
x
     [,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6

# 1st row
do.call(`[`, alist(x, 1, ))
[1] 1 4

# 2nd column
do.call(`[`, alist(x, , 2))
[1] 4 5 6
Run Code Online (Sandbox Code Playgroud)

来自?alist:

'alist'处理它的参数,好像它们描述了函数参数.因此不评估值,并且允许没有值的标记参数,而'list'只是忽略它们.'alist'最常用于'formals'.


一种动态选择提取哪个维度的方法.要创建alist所需长度的初始值,请参见此处(Hadley,使用bquote)或此处(使用alist).

m <- array(1:24, c(2,3,4))
ndims <- 3
a <- rep(alist(,)[1], ndims)
for(i in seq_len(ndims))
{
    slice <- a
    slice[[i]] <- 1
    print(do.call(`[`, c(list(m), slice)))
}

     [,1] [,2] [,3] [,4]
[1,]    1    7   13   19
[2,]    3    9   15   21
[3,]    5   11   17   23

     [,1] [,2] [,3] [,4]
[1,]    1    7   13   19
[2,]    2    8   14   20

     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
Run Code Online (Sandbox Code Playgroud)


42-*_*42- 11

我总是TRUE在这个例子中用作占位符:

> x
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
> do.call("[", list(x, TRUE,1))
[1] 1 2
Run Code Online (Sandbox Code Playgroud)

让我们使用一个更复杂的x例子:x <- array(1:36, c(2,9,2)那么,如果希望在下标列表中替换一个向量,它将恢复所有第一维和第二维以及第三维的第二个"切片":

shortdim <- 3
short.idx <- 2
dlist <- rep(TRUE, length(dim(x)) )
dlist <- as.list(rep(TRUE, length(dim(x)) ))

> dlist
[[1]]
[1] TRUE

[[2]]
[1] TRUE

[[3]]
[1] TRUE

> dlist[shortdim] <- 2
> do.call("[", c(list(x), dlist) )
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,]   19   21   23   25   27   29   31   33   35
[2,]   20   22   24   26   28   30   32   34   36
Run Code Online (Sandbox Code Playgroud)

有时候有用的另一点是逻辑索引被循环使用,因此您可以使用c(TRUE,FALSE)来挑选其他所有项:

(x<-array(1:36, c(2,9,2)))
, , 1

     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,]    1    3    5    7    9   11   13   15   17
[2,]    2    4    6    8   10   12   14   16   18

, , 2

     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,]   19   21   23   25   27   29   31   33   35
[2,]   20   22   24   26   28   30   32   34   36

> x[TRUE,c(TRUE,FALSE), TRUE]
, , 1

     [,1] [,2] [,3] [,4] [,5]
[1,]    1    5    9   13   17
[2,]    2    6   10   14   18

, , 2

     [,1] [,2] [,3] [,4] [,5]
[1,]   19   23   27   31   35
[2,]   20   24   28   32   36
Run Code Online (Sandbox Code Playgroud)

并且可以对每个其他项目进行进一步的变化.尝试使用c(FALSE,FALSE,TRUE)来获取以item-3开头的每个第三个项目.


flo*_*del 9

不是一个直接的答案,但我会演示asub作为替代,因为我很确定这是OP最终会追求的.

library(abind)
Run Code Online (Sandbox Code Playgroud)

提取第1行:

asub(x, idx = list(1), dims = 1)
Run Code Online (Sandbox Code Playgroud)

提取第二和第三列:

asub(x, idx = list(2:3), dims = 2)
Run Code Online (Sandbox Code Playgroud)

shortdimOP想要从维度中删除最后一项:

asub(x, idx = list(1:(dim(x)[shortdim]-1)), dims = shortdim)
Run Code Online (Sandbox Code Playgroud)

您也可以使用否定索引,这样也可以使用:

asub(x, idx = list(-dim(x)[shortdim]), dims = shortdim)
Run Code Online (Sandbox Code Playgroud)

最后,我会提到该函数有一个drop选项就像[那样.