Gabriel123
Gabriel123

Reputation: 456

Extract series of successive vectors from matrix

I have a large matrix, say for simplification:

> mat = matrix(c(1:50), ncol = 5)
> mat
      [,1] [,2] [,3] [,4] [,5]
 [1,]    1   11   21   31   41
 [2,]    2   12   22   32   42
 [3,]    3   13   23   33   43
 [4,]    4   14   24   34   44
 [5,]    5   15   25   35   45
 [6,]    6   16   26   36   46
 [7,]    7   17   27   37   47
 [8,]    8   18   28   38   48
 [9,]    9   19   29   39   49
[10,]   10   20   30   40   50

I want to extract successively all possible vertical vectors composed of 3 elements from each column, e.g. (1,2,3), (2,3,4),...,(11,12,13), (12,13,14),... and generate a 3-by-X matrix composed of all these vectors. Something that would look like this:

      [,1] [,2] [,3] 
 [1,]    1   2   3 
 [2,]    2   3   4 
 [3,]    3   4   5 
 etc.    .   .   . 
 [5,]    11   12   13 
 [6,]    12   13   14 
 [7,]    13   14   15 
 etc.    ..   ..   .. 
 [9,]    21   22   23 
[10,]    22   23   24 

I have tried using the lapply and cbind functions, as well as a more generic for loop, but it shows "incorrect number of dimensions". Thanks for your help!

Upvotes: 3

Views: 67

Answers (2)

akrun
akrun

Reputation: 887971

We can do this with base R

do.call(rbind, lapply(as.data.frame(mat), embed, 3))[,3:1]
#       [,1] [,2] [,3]
# [1,]    1    2    3
# [2,]    2    3    4
# [3,]    3    4    5
# [4,]    4    5    6
# [5,]    5    6    7
# [6,]    6    7    8
# [7,]    7    8    9
# [8,]    8    9   10
# [9,]   11   12   13
#[10,]   12   13   14
#[11,]   13   14   15
#[12,]   14   15   16
#[13,]   15   16   17
#[14,]   16   17   18
#[15,]   17   18   19
#[16,]   18   19   20
#[17,]   21   22   23
#[18,]   22   23   24
#[19,]   23   24   25
#[20,]   24   25   26
#[21,]   25   26   27
#[22,]   26   27   28
#[23,]   27   28   29
#[24,]   28   29   30
#[25,]   31   32   33
#[26,]   32   33   34
#[27,]   33   34   35
#[28,]   34   35   36
#[29,]   35   36   37
#[30,]   36   37   38
#[31,]   37   38   39
#[32,]   38   39   40
#[33,]   41   42   43
#[34,]   42   43   44
#[35,]   43   44   45
#[36,]   44   45   46
#[37,]   45   46   47
#[38,]   46   47   48
#[39,]   47   48   49
#[40,]   48   49   50

Upvotes: 2

Florian
Florian

Reputation: 25435

Like this?

EDIT: modified the function from 'print' to 'c' within rollapply based on Grothendieck's suggestion in comment.

library(zoo)
do.call(rbind,lapply(as.data.frame(mat), function(x) rollapply(x,width=3,c)))

      [,1] [,2] [,3]
 [1,]    1    2    3
 [2,]    2    3    4
 [3,]    3    4    5
 [4,]    4    5    6
 [5,]    5    6    7
 [6,]    6    7    8
 [7,]    7    8    9
 [8,]    8    9   10
 [9,]   11   12   13
[10,]   12   13   14
[11,]   13   14   15
[12,]   14   15   16
[13,]   15   16   17
[14,]   16   17   18
[15,]   17   18   19
[16,]   18   19   20
[17,]   21   22   23
[18,]   22   23   24
[19,]   23   24   25
[20,]   24   25   26
[21,]   25   26   27
[22,]   26   27   28
[23,]   27   28   29
[24,]   28   29   30
[25,]   31   32   33
[26,]   32   33   34
[27,]   33   34   35
[28,]   34   35   36
[29,]   35   36   37
[30,]   36   37   38
[31,]   37   38   39
[32,]   38   39   40
[33,]   41   42   43
[34,]   42   43   44
[35,]   43   44   45
[36,]   44   45   46
[37,]   45   46   47
[38,]   46   47   48
[39,]   47   48   49
[40,]   48   49   50

Upvotes: 2

Related Questions