user3437823
user3437823

Reputation: 351

Build summary table from matrix

I have this matrix

mdat <- matrix(c(0,1,1,1,0,0,1,1,0,1,1,1,1,0,1,1,1,1,0,1), nrow = 4, ncol = 5, byrow = TRUE)

    [,1] [,2] [,3] [,4] [,5]
[1,]    0    1    1    1    0
[2,]    0    1    1    0    1
[3,]    1    1    1    0    1
[4,]    1    1    1    0    1

and I'm trying to build T:

     T1 T2 T3
row1  1  2  4
row2  2  2  3
row3  2  5  5
row4  3  1  3
row5  3  5  5
row6  4  1  3
row7  4  5  5

where for each row in mdat: T1 shows mdat row number T2 shows mdat column where there's the first 1 T3 shows mdat column where there's the last consecutive 1.

Therefore

row1 in T is [1 2 4] because for row 1 in mdat the first 1 is in column 2 and the last consecutive 1 is in column 4.

row2 in T is [2 2 3] because for row 2 in mdat the first 1 is in column 2 and the last consecutive 1 is in column 3.

This is my try:

for (i in 1:4){ 
 for (j in 1:5) {

   if (mdat[i,j]==1) {T[i,1]<-i;T[i,2]<-j;
cont<-0;
while (mdat[i,j+cont]==1){
    cont<-cont+1;
    T[i,3]<-cont}
}
}
}

Upvotes: 1

Views: 72

Answers (2)

Michael Lawrence
Michael Lawrence

Reputation: 1021

Try the Bioconductor IRanges package:

library(IRanges)
r <- unlist(slice(split(Rle(mdat), row(mdat)), 1, rangesOnly=TRUE)))
r

IRanges of length 7
    start end width names
[1]     2   4     3     1
[2]     2   3     2     2
[3]     5   5     1     2
[4]     1   3     3     3
[5]     5   5     1     3
[6]     1   3     3     4
[7]     5   5     1     4

EDIT: optimized

Upvotes: 2

MrFlick
MrFlick

Reputation: 206401

Here's a strategy using apply/rle as Richard suggested.

xx<-apply(mdat, 1, function(x) {
    r <- rle(x)
    w <- which(r$values==1)
    l <- r$lengths[w]
    s <- cumsum(c(0,r$lengths))[w]+1
    cbind(start=s,stop=s+l-1)
})
do.call(rbind, Map(cbind, row=seq_along(xx), xx))

We start by finding the runs of 1 on each row using the "values" property of the rle and we calculate their start and stop positions using the "lengths" property. We turn this data into a list of two column matrices with one list item per row of the original matrix.

Now we use Map to add the row number back onto the matrix and then we rbind all the results. That seems to give you the data you're after

     row start stop
[1,]   1     2    4
[2,]   2     2    3
[3,]   2     5    5
[4,]   3     1    3
[5,]   3     5    5
[6,]   4     1    3
[7,]   4     5    5

Upvotes: 3

Related Questions