PCK1992 PCK1992 - 2 months ago 7
R Question

Changing blocks of values in a large matrix in R

I have large matrix of 1000x1000 entries. The 1's are organized in blocks, they always seperated from the other blocks by not overlapping on the row or column of the next block. To give you an example with a 12x12 matrix that consists of 3 blocks of 1s:

111100000000
111100000000
111100000000
111100000000
000011110000
000011110000
000011110000
000011110000
000000001111
000000001111
000000001111
000000001111


I want R to transfer the matrix into something like this(no matter the size of the matrix):

111100000000
111100000000
111100000000
111100000000
000022220000
000022220000
000022220000
000022220000
000000003333
000000003333
000000003333
000000003333


Thanks in advance!

Data

structure(c(1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0,
0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
1), .Dim = c(12L, 12L))

Answer

Multiply the matrix by the block group. 0's will remain the same and ones will take their group value:

len <- sum(mat[,1])
mat * rep(1:(nrow(mat)/len), each=len)
#       [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
# [1,]     1    1    1    1    0    0    0    0    0     0     0     0
# [2,]     1    1    1    1    0    0    0    0    0     0     0     0
# [3,]     1    1    1    1    0    0    0    0    0     0     0     0
# [4,]     1    1    1    1    0    0    0    0    0     0     0     0
# [5,]     0    0    0    0    2    2    2    2    0     0     0     0
# [6,]     0    0    0    0    2    2    2    2    0     0     0     0
# [7,]     0    0    0    0    2    2    2    2    0     0     0     0
# [8,]     0    0    0    0    2    2    2    2    0     0     0     0
# [9,]     0    0    0    0    0    0    0    0    3     3     3     3
# [10,]    0    0    0    0    0    0    0    0    3     3     3     3
# [11,]    0    0    0    0    0    0    0    0    3     3     3     3
# [12,]    0    0    0    0    0    0    0    0    3     3     3     3

Edit

If the block groups vary within the matrix we will have to differentiate one block ending and another beginning using this instead:

library(data.table)
mat * rleid(apply(mat, 1, paste, collapse=""))
Comments