2d matrix in 3d complex array in r

I have a dataframe data

in R of dim 120,000 rows by 5 columns.

Every 300 lines represents a frame measured at different time intervals (i.e. 400 frames)

Act

I tried to use array(data, c(300, 5, 400))

Expected

Make this framework into a 3d array, dividing data

every 300 lines and join these 400 matrices one after another.

Actual

Reads the values ​​down the first column data

and places them in the first part of the array.

+3


source to share


2 answers


Another variant:

 m1 <- matrix(1:(300*400*5), nrow=300*400, ncol=5)
 lst <- lapply(split(seq_len(nrow(m1)),(seq_len(nrow(m1))-1) %/%300 +1),
                         function(i) m1[i,])

 arr1 <- array(0, dim=c(300,5,400))
 for(i in 1:400){
 arr1[,,i] <- lst[[i]]
 }

m1[297:300,]
#     [,1]   [,2]   [,3]   [,4]   [,5]
#[1,]  297 120297 240297 360297 480297
#[2,]  298 120298 240298 360298 480298
#[3,]  299 120299 240299 360299 480299
#[4,]  300 120300 240300 360300 480300

 tail(arr1[,,1],4)
 #      [,1]   [,2]   [,3]   [,4]   [,5]
 #[297,]  297 120297 240297 360297 480297
 #[298,]  298 120298 240298 360298 480298
 #[299,]  299 120299 240299 360299 480299
 #[300,]  300 120300 240300 360300 480300

      



Or as suggested by @Ananda Mahto

library(abind)
arr2 <-  abind(lapply(split(seq_len(nrow(m1)), 
           (seq_len(nrow(m1))-1) %/% 300 + 1), function(x) m1[x, ]), along = 3)

      

+4


source


Here's an approach using dim<-

and aperm

:

Sample data:

set.seed(1)
mat <- matrix(sample(100, 12 * 5, TRUE), ncol = 5)
mat
#       [,1] [,2] [,3] [,4] [,5]
#  [1,]   27   69   27   80   74
#  [2,]   38   39   39   11   70
#  [3,]   58   77    2   73   48
#  [4,]   91   50   39   42   87
#  [5,]   21   72   87   83   44
#  [6,]   90  100   35   65   25
#  [7,]   95   39   49   79    8
#  [8,]   67   78   60   56   10
#  [9,]   63   94   50   53   32
# [10,]    7   22   19   79   52
# [11,]   21   66   83    3   67
# [12,]   18   13   67   48   41

      

Slicing and slicing:

Sliced <- aperm(`dim<-`(t(mat), list(5, 3, 4)), c(2, 1, 3))

Sliced
# , , 1
# 
#      [,1] [,2] [,3] [,4] [,5]
# [1,]   27   69   27   80   74
# [2,]   38   39   39   11   70
# [3,]   58   77    2   73   48
# 
# , , 2
# 
#      [,1] [,2] [,3] [,4] [,5]
# [1,]   91   50   39   42   87
# [2,]   21   72   87   83   44
# [3,]   90  100   35   65   25
# 
# , , 3
# 
#      [,1] [,2] [,3] [,4] [,5]
# [1,]   95   39   49   79    8
# [2,]   67   78   60   56   10
# [3,]   63   94   50   53   32
# 
# , , 4
# 
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    7   22   19   79   52
# [2,]   21   66   83    3   67
# [3,]   18   13   67   48   41

      

Adjust the numbers to match your data.




When destroyed, we get:

  • t(mat)

    : transfers your matrix (so we now have 5 x 12).
  • dim<-(..., list(...))

    : will convert this to an array, in this case 5 (string) x 3 (col) x 4 (third dimension).
  • aperm

    : the result of the last step is a string, so we need to convert it to columns, so this is similar to t

    but with multiple dimensions.

They are also very efficient operations. Here's a comparison of this approach to @ akrun's:

m1 <- matrix(1:(300*400*5), nrow=300*400, ncol=5)

am <- function() {
  aperm(`dim<-`(t(m1), list(5, 300, 400)), c(2, 1, 3))
}

ak <- function() {
  lst <- lapply(split(seq_len(nrow(m1)),(seq_len(nrow(m1))-1) %/%300 +1),
                function(i) m1[i,])

  arr1 <- array(0, dim=c(300,5,400))
  for(i in 1:400){
    arr1[,,i] <- lst[[i]]
  }
  arr1
}

library(microbenchmark)
microbenchmark(am(), ak(), times = 20)
# Unit: milliseconds
#  expr       min        lq    median        uq      max neval
#  am()  19.09133  27.63269  31.18292  67.12434 146.2673    20
#  ak() 496.11494 518.71223 550.02215 591.27266 699.9834    20

      

+5


source







All Articles