gg_gal_99
gg_gal_99

Reputation: 41

How to shuffle values in a matrix or data frame so that each value only occurs once in each row/column?

How to shuffle values in a matrix or data frame so that each value only occurs once in each row/column in R?

For example, here is what I have:

A, A, A, A
B, B, B, B
C, C, C, C
D, D, D, D
E, E, E, E
F, F, F, F
G, G, G, G

What I Want:

A, B, C, D
B, C, D, E
C, D, E, F
D, E, F, G
E, F, G, A
F, G, A, B
G, A, B, C

I either need to shift the column up/down and wrap it to maintain my inputs or do it through some sort of shuffle function that shuffles the columns in a way that still ensures the rows do not repeat.

Upvotes: 3

Views: 218

Answers (1)

ThomasIsCoding
ThomasIsCoding

Reputation: 101034

You can try outer + %% to produce circular shift

v <- LETTERS[1:4]
out <- matrix(
  v[outer(seq_along(v) - 1, seq_along(v) - 1, `+`) %% length(v) + 1],
  nrow = length(v)
)

such that

> out
     [,1] [,2] [,3] [,4]
[1,] "A"  "B"  "C"  "D"
[2,] "B"  "C"  "D"  "A"
[3,] "C"  "D"  "A"  "B"
[4,] "D"  "A"  "B"  "C"

Update If your matrix is not square, you can try the code like below

v <- LETTERS[1:7]
out <- t(
  head(
    matrix(
      v[outer(seq_along(v) - 1, seq_along(v) - 1, `+`) %% length(v) + 1],
      nrow = length(v)
    ), 4
  )
)

which gives

> out
     [,1] [,2] [,3] [,4]
[1,] "A"  "B"  "C"  "D"
[2,] "B"  "C"  "D"  "E"
[3,] "C"  "D"  "E"  "F" 
[4,] "D"  "E"  "F"  "G"
[5,] "E"  "F"  "G"  "A"
[6,] "F"  "G"  "A"  "B"
[7,] "G"  "A"  "B"  "C"

Upvotes: 3

Related Questions