Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R: Apply cut using row-specific breaks

Tags:

r

matrix

apply

I would like to transform a matrix of latent scores to observed scores.

One can do so by apply break points/thresholds to the original matrix, thus ending up having a new, categorical matrix. Doing so is simple, for example:

#latent variable matrix
true=matrix(c(1.45,2.45,3.45,
              0.45,1.45,2.45,
              3.45,4.45,5.45)
,ncol=3,byrow=TRUE)

#breaks for the cut function
br=c(-Inf,1,2,3,4,Inf)

#apply cut function to latent variable
observed=apply(true,c(1,2),cut,breaks=br,labels=FALSE,include.lowest=TRUE)

However, what I need to do is apply different breaks to every row of the original matrix. These thresholds are stored in a matrix:

#matrix of breaks for the cut function
br=matrix(c(-Inf,1,2,3,4,Inf,
             -Inf,1.5,2.5,3.5,4.5,Inf,
             -Inf,2,3,4,5,Inf)
,ncol=6,byrow=TRUE)

That is, row 1 of the br matrix should serve as the breaks for row 1 of the true matrix and for that row only, row 2 of br are the breaks for row 2 of true, etc.

Using the following does not seem to do the work:

for (i in 1:nrow(true)) {
  observed[i,]=apply(true[i,],c(1,2),cut,breaks=br[i,],labels=FALSE,include.lowest=TRUE)
}

Do you have any ideas? Is there any way to apply the respective br line to the respective true line and save it in the same line of observed?

Many thanks in advance!

KH

like image 619
user4507481 Avatar asked Nov 01 '22 10:11

user4507481


1 Answers

Using sapply over the number of rows,(essentially just hiding the for loop) gives you what you want:

values = sapply(1:nrow(true), function(i) 
     cut(true[i,], br[i,], labels=FALSE, include.lowest=TRUE)))
values = t(values)

Unfortunately we need an extra transpose step to get the matrix the correct way.


Regarding your for loop in your question, when you just subset a row, i.e. true[i,] we just get a vector. This causes the apply to break. To avoid the vector you need an a additional argument

true[i,, drop=FALSE]
like image 52
csgillespie Avatar answered Nov 15 '22 06:11

csgillespie