Home > Mobile >  Cycle each consecutive row of a matrix to the right by 1 position
Cycle each consecutive row of a matrix to the right by 1 position

Time:06-20

I don't even really know how to describe what I want to do, so hopefully the title makes at least some sense.

Better if I show you:

I have a simple 3x5 matrix of letters a to e:

matrix(data = rep(letters[1:5], 3), nrow = 3, ncol = 5, byrow = TRUE)

It gives this:

     [,1] [,2] [,3] [,4] [,5]
[1,] "a"  "b"  "c"  "d"  "e" 
[2,] "a"  "b"  "c"  "d"  "e" 
[3,] "a"  "b"  "c"  "d"  "e"

I would like to change it to this without typing it manually:

     [,1] [,2] [,3] [,4] [,5]
[1,] "a"  "b"  "c"  "d"  "e" 
[2,] "e"  "a"  "b"  "c"  "d" 
[3,] "d"  "e"  "a"  "b"  "c"

I'm thinking some kind of loop system or similar, but I have no idea where to start.

CodePudding user response:

For the simple case you might try this for loop.

n <- dim(m3)[2]
for (i in seq_len(nrow(m))[-1]) {
  m3[i, ] <- c(m3[i, (n - i   2):n], m3[i, 1:(n - i   1)])
}
m3
#     [,1] [,2] [,3] [,4] [,5]
# [1,] "a"  "b"  "c"  "d"  "e" 
# [2,] "e"  "a"  "b"  "c"  "d" 
# [3,] "d"  "e"  "a"  "b"  "c" 

To let the pattern repeat for a longer matrix, we might generalize:

n <- dim(m7)[2]
for (i in seq_len(nrow(m7))[-1]) {
  j <- i %% 5
  if (j == 0) j <- 5
  if (j > 1) m7[i, ] <- c(m7[i, (n - j   2):n], m7[i, 1:(n - j   1)])
}
m7
#     [,1] [,2] [,3] [,4] [,5]
# [1,] "a"  "b"  "c"  "d"  "e" 
# [2,] "e"  "a"  "b"  "c"  "d" 
# [3,] "d"  "e"  "a"  "b"  "c" 
# [4,] "c"  "d"  "e"  "a"  "b" 
# [5,] "b"  "c"  "d"  "e"  "a" 
# [6,] "a"  "b"  "c"  "d"  "e" 
# [7,] "e"  "a"  "b"  "c"  "d" 

Data:

m3 <- matrix(data=letters[1:5], nrow=3, ncol=5, byrow=TRUE)
m7 <- matrix(data=letters[1:5], nrow=7, ncol=5, byrow=TRUE)

CodePudding user response:

You can create a variable called ord ord <- seq_len(ncol(m))

Within the map function use the ord and the max(ord) to create some integers that will be used to subset the array.

Then rbinding the result with do.call(rbind)

Where m is the matrix

library(purrr)

do.call(rbind, map2(ord, nrow(m),   \(x,y) 
                    m[y, c(x:max(ord),
                           ord[- (x:max(ord))])]
                    )[c(1,rev(ord))]
        )
    [,1] [,2] [,3] [,4] [,5]
[1,] "a"  "b"  "c"  "d"  "e" 
[2,] "e"  "a"  "b"  "c"  "d" 
[3,] "d"  "e"  "a"  "b"  "c" 
[4,] "c"  "d"  "e"  "a"  "b" 
[5,] "b"  "c"  "d"  "e"  "a" 
[6,] "a"  "b"  "c"  "d"  "e"
  • Related