R: counting and recoding consecutive values in a matrix -


i working matrix containing large number of na. record length of each sequence of na in new matrix.

the following example should more plain.

#generating random 5x5 population matrix 15 na m=matrix(sample(1:9,25,t),5) m[sample(1:length(m),15,f)]=na dimnames(m)=list(paste(rep("city",dim(m)[1]),1:dim(m)[1],sep=""),paste(rep("year",dim(m)[2]),1:dim(m)[2],sep="")) m        year1 year2 year3 year4 year5 city1     2    na    na    na    na city2    na    na    na     6     8 city3     1    na    na     6    na city4    na     5    na    na     1 city5     8    na     1    na     2 

the desired output following. e.g. 4 4 4 4 denotes sequence of 4 consecutive na.

          year1 year2 year3 year4 year5 city1     0     4     4     4     4 city2     3     3     3     0     0 city3     0     2     2     0     1 city4     1     0     2     2     0 city5     0     1     0     1     0 

do have idea of how go that?

not efficient code ever:

r1=c(1,1,na,1,1) r2=c(1,na,na,1,1) r3=c(1,na,na,na,1) r4=c(na,na,1,1,1) r5=c(1,1,1,na,na) m=rbind(r1,r2,r3,r4,r5) 

like @pascal pointed out, approach convert entire matrix characters, can assign 1s 0s instead , this:

m[m == 1] <- 0  (xx <- t(apply(m, 1, function(x) {   s <- sum(is.na(x))   if (is.na(x[1])) x[is.na(x)] <- rep(4, s) else     if (is.na(tail(x, 1))) x[is.na(x)] <- rep(5, s) else      x[is.na(x)] <- s   x })))  #    [,1] [,2] [,3] [,4] [,5] # r1    0    0    1    0    0 # r2    0    2    2    0    0 # r3    0    3    3    3    0 # r4    4    4    0    0    0 # r5    0    0    0    5    5 

this desired output. if don't believe me, convert 0s 1s , assign letters based on integers

xx[xx > 0] <- letters[xx[xx > 0]] xx[xx == '0'] <- 1   r1=c(1,1,"a",1,1) r2=c(1,"b","b",1,1) r3=c(1,"c","c","c",1) r4=c("d","d",1,1,1) r5=c(1,1,1,"e","e") r=rbind(r1,r2,r3,r4,r5)   identical(r, xx) # [1] true 

Comments