在3D数组中添加列或行

时间:2014-12-24 13:04:03

标签: arrays r

我有这样的数组:

, , 1

     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9

, , 2

     [,1] [,2] [,3]
[1,]   10   13   16
[2,]   11   14   17
[3,]   12   15   18

, , 3

     [,1] [,2] [,3]
[1,]   19   22   25
[2,]   20   23   26
[3,]   21   24   27

我想为每个组件添加一个列,填充0,最后得到这个:

, , 1

     [,1] [,2] [,3] [,4]
[1,]    1    4    7   0
[2,]    2    5    8   0
[3,]    3    6    9   0

, , 2

     [,1] [,2] [,3] [,4]
[1,]   10   13   16   0
[2,]   11   14   17   0
[3,]   12   15   18   0

, , 3

     [,1] [,2] [,3] [,4]
[1,]   19   22   25   0
[2,]   20   23   26   0
[3,]   21   24   27   0

使用R?

有一种简单的方法吗?

3 个答案:

答案 0 :(得分:7)

这是一种方式:

library(abind)
abind(x, array(0, replace(dim(x), 2, 1)), along = 2)

还有一个:

aperm(apply(x, c(1, 3), c, 0), c(2, 1, 3))

答案 1 :(得分:2)

您也可以尝试类似的东西(虽然它有点手动,但应该比其他基础R解决方案更快)

indx <- dim(df) + c(0, 1, 0)
array(sapply(1:indx[3], function(x) cbind(df[,,x], 0)), indx)

一些基准

n <- 1e5
df <- array(1:27, c(3, 3, n))

library(abind)
library(microbenchmark)

flodel1 <- function(x) abind(x, array(0, replace(dim(x), 2, 1)), along = 2)
flodel2 <- function(x) aperm(apply(x, c(1, 3), c, 0), c(2, 1, 3))
David <- function(x) {indx <- dim(x) + c(0, 1, 0) ; array(sapply(seq_len(indx[3]), function(y) cbind(x[,,y], 0)), indx)}

Res <- microbenchmark(flodel1(df),
                      flodel2(df),
                      David(df))

# Unit: milliseconds
#        expr      min        lq      mean    median       uq      max neval
# flodel1(df)  45.8943  65.37496  90.68902  90.24751 107.5991 159.9881   100
# flodel2(df) 553.4831 634.73127 673.95636 679.79709 710.0540 808.6248   100
#   David(df) 434.9524 531.85597 576.77011 555.46865 626.3344 757.9358   100

答案 2 :(得分:1)

只是为了挑战,除非我错过了一些东西,否则另一个想法(带有一些额外的酱油)似乎是有效的:

add_col_or_row = function(x, n = 1, add_col = T, fill = 0)
{
   m1 = matrix(x, ncol = if(add_col) nrow(x) * ncol(x) else nrow(x), byrow = T)
   m2 = matrix(fill, nrow = if(add_col) dim(x)[3] else prod(dim(x)[-1]), 
                     ncol = if(add_col) nrow(x) * n else n)
   array(t(cbind(m1, m2)), 
         c(nrow(x) + ((!add_col) * n), ncol(x) + (add_col * n), dim(x)[3]))
}

aa = array(1:24, c(3, 4, 2))

aa
#, , 1
#
#     [,1] [,2] [,3] [,4]
#[1,]    1    4    7   10
#[2,]    2    5    8   11
#[3,]    3    6    9   12
#
#, , 2
#
#     [,1] [,2] [,3] [,4]
#[1,]   13   16   19   22
#[2,]   14   17   20   23
#[3,]   15   18   21   24

add_col_or_row(aa, 2, T)
#, , 1
#
#     [,1] [,2] [,3] [,4] [,5] [,6]
#[1,]    1    4    7   10    0    0
#[2,]    2    5    8   11    0    0
#[3,]    3    6    9   12    0    0
#
#, , 2
#
#     [,1] [,2] [,3] [,4] [,5] [,6]
#[1,]   13   16   19   22    0    0
#[2,]   14   17   20   23    0    0
#[3,]   15   18   21   24    0    0
#

add_col_or_row(aa, 2, F)
#, , 1
#
#     [,1] [,2] [,3] [,4]
#[1,]    1    4    7   10
#[2,]    2    5    8   11
#[3,]    3    6    9   12
#[4,]    0    0    0    0
#[5,]    0    0    0    0
#
#, , 2
#
#     [,1] [,2] [,3] [,4]
#[1,]   13   16   19   22
#[2,]   14   17   20   23
#[3,]   15   18   21   24
#[4,]    0    0    0    0
#[5,]    0    0    0    0

使用David Arenburg的数据进行基准测试:

microbenchmark(flodel1(df), add_col_or_row(df), times = 20)
#Unit: milliseconds
#               expr      min       lq   median       uq      max neval
#        flodel1(df) 35.69158 54.88014 55.58363 56.40300 58.31250    20
# add_col_or_row(df) 19.87134 38.57792 39.11297 39.58347 44.59873    20

identical("dimnames<-"(flodel1(df), NULL), add_col_or_row(df))
#[1] TRUE