The order of the rows in the matrix, excluding zero values in R
I have a "mat" matrix containing null values. For instance:
> mat
[,1] [,2] [,3] [,4] [,5]
[1,] 2 5 1 4 3
[2,] 0 0 2 4 3
[3,] 2 5 0 3 1
[4,] 4 5 2 3 1
[5,] 1 5 2 3 4
[6,] 2 5 1 4 3
[7,] 0 0 0 5 1
[8,] 1 5 4 2 3
[9,] 3 5 1 0 2
[10,] 2 5 4 1 3
I would like to have matrix row index order excluding null values. However, the zero values of each row should remain in the reduced matrix, but at the end. For example, for a given matrix "mat" the result should be like this:
> res
[,1] [,2] [,3] [,4] [,5]
[1,] 3 1 5 4 2
[2,] 3 5 4 0 0
[3,] 5 1 4 2 0
[4,] 5 3 4 1 2
[5,] 1 3 4 5 2
[6,] 3 1 5 4 2
[7,] 5 4 0 0 0
[8,] 1 4 5 3 2
[9,] 3 5 1 2 0
[10,] 4 1 5 3 2
I came up with the following code:
if (sum(mat==0)>0){ # mat contains zeros
mat[which(mat==0, arr.ind = TRUE)]=NA
l=apply(mat, 1, function(x) order(x, na.last = NA))
mat=t(sapply(l, '[', 1:max(sapply(l, length))))
mat[which(is.na(mat), arr.ind = TRUE)]=0
return(mat)
}
Do you guys have a better idea or a better algorithm for this in R? thank
Test data:
mat <- structure(c(2, 0, 2, 4, 1, 2, 0, 1, 3, 2, 5, 0, 5, 5, 5, 5,
0, 5, 5, 5, 1, 2, 0, 2, 2, 1, 0, 4, 1, 4, 4, 4, 3, 3, 3, 4, 5, 2, 0, 1,
3, 3, 1, 1, 4, 3, 1, 3, 2, 3), .Dim = c(10L, 5L))
, , res, - , . , , ( ), , :
res <- apply(mat,1,function(i){
out <- order(i)
iszero <- i == 0
c(out[!iszero[out]], i[iszero])
})
res <- t(res)
> res
[,1] [,2] [,3] [,4] [,5]
[1,] 3 1 5 4 2
[2,] 3 5 4 0 0
[3,] 5 1 4 2 0
[4,] 5 3 4 1 2
[5,] 1 3 4 5 2
[6,] 3 1 5 4 2
[7,] 5 4 0 0 0
[8,] 1 4 5 3 2
[9,] 3 5 1 2 0
[10,] 4 1 5 3 2
res, .