簡體   English   中英

在3D數組中添加列或行

[英]Adding column or row in 3D array

我有一個像這樣的數組:

, , 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?

這是一種方式:

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))

您也可以嘗試類似的東西(雖然它有點手動,但應該比其他基礎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

只是為了挑戰,除非我錯過了一些東西,否則另一個想法(帶有一些額外的醬油)似乎是有效的:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM