不要在对三维数组进行子集操作时删除维度。

6

A 成为一个 1 x 2 x 2 数组:

> A <- array(0, dim=c(1,2,2))
> A
, , 1

     [,1] [,2]
[1,]    0    0

, , 2

     [,1] [,2]
[1,]    0    0

那么A[,,1]是无量纲的:

> A[,,1]
[1] 0 0

我想要:

     [,1] [,2]
[1,]    0    0
< p > drop 参数没有产生我想要的结果:

> A[,,1,drop=FALSE]
, , 1

     [,1] [,2]
[1,]    0    0

我发现这很烦人。而且有缺陷,因为R将向量识别为列矩阵,而不是行矩阵。

当然,我可以使用matrix(A[,,1], 1, 2)。是否有更方便的方法?

4个回答

2
我们可以根据所提取的MARGIN分配dim
`dim<-`(A[, ,1], apply(A, 3, dim)[,1])
 #     [,1] [,2]
 #[1,]    0    0

举另一个例子

B <- array(0, dim = c(2, 1, 2))
`dim<-`(B[, ,1], apply(B, 3, dim)[,1])
 #    [,1]
#[1,]    0
#[2,]    0

如果我们使用的是一个封装好的解决方案,那么从abind中使用adrop函数可以得到预期的输出结果。

library(abind)
adrop(A[,,1,drop=FALSE], drop = 3)
#      [,1] [,2]
# [1,]    0    0

adrop(B[,,1,drop=FALSE], drop = 3)
#     [,1]
#[1,]    0
#[2,]    0

1
虽然不太好,但似乎没有更好的答案了,所以我接受了。谢谢。顺便提一下,看看我的答案,keep包可能会有帮助。 - Stéphane Laurent

1
t(A[,,1])
 [,1] [,2]
[1,]    0    0

我从你的评论中了解到,R将向量识别为列矩阵。我认为对其进行转置可以得到你想要的结果,并且更加方便。

是的,但是如果A2 x 1 x n,我希望A[,,1]2 x 1,而这种方法会给出1 x 2。我想要一个可以同时满足两种情况期望的解决方案。 - Stéphane Laurent
在这些情况下,你可以t(t(A[,,1]))。但实际上这并不是很好,因为它取决于具体情况。 - denis

1

很遗憾,这个问题没有简单的解决办法。使用 drop = TRUE,任何维度为 1 的部分都会被删除。如果查看 src/main/subset.c 中的 ArraySubset 源代码,您可以看到这一点。在函数的末尾,我们可以看到:

if (drop)
    DropDims(result);

DropDims 函数定义在 src/main/array.c 中。在该函数中,我们看到

n = 0;
for (i = 0; i < ndims; i++)
    if (dim[i] != 1) n++;

在该函数的其他地方,我们看到大小为一的维度被忽略。
很烦人的是R从结果中确定了丢弃行为。如果R仅删除长度为一的索引维度,那么在这个例子中预期的行为将更加自然。
话虽如此,以下内容可能很丑陋,但对于您的用例可能有效。
`dim<-`(A[,,1], dim(A)[-3])
 #>      [,1] [,2]
 #> [1,]    0    0

这种方法不太适用于泛化,但如果按单个坐标索引,则可行。

0

另一个解决方案是使用keep包。

> library(keep)
> A <- karray(0, dim=c(1,2,2))
> A[,,1]
     [,1] [,2]
[1,]    0    0
attr(,"class")
[1] "keep"    "numeric"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接