I have an O = n x m matrix containing 0s and 1s that I have to transform into m matrices of M_j = n x n dimension. Each of those M_j matrices will have value 1 if: element i of column j of the O matrix is equal to 1 & element k of column j of the O matrix is equal to 0; and will have value 0 otherwise. I've managed to create a script using a triple for-loop and an if statement in R that does this quite easily, but I'm sure there must be a much more efficient way to do this. However, I can't really think of how to vectorize/use sapply/ something else. Any suggestions?
My sample code:
o <- data.frame(s1 = c(1,0,0),
s2 = c(0,1,1),
s3 = c(1,0,1),
s4 = c(0,1,1))
#### MATRICES M (4 matrices of 3x3) ----
m <- list()
n_ocup <- nrow(o)
n_skill <- ncol(o)
for (i in 1:n_skill){
print(paste0("########### M", i, " ###########"))
temp_m <- matrix(nrow = n_ocup, ncol = n_ocup, 0)
temp_o <- o[,i]
for (j in 1:nrow(temp_m)){
for (k in 1:ncol(temp_m)){
if (temp_o[j,1]==1 & temp_o[k,1]==0){
temp_m[k,j] <- 1 #seems backwards but it's OK
}
}
}
m[[i]] <- temp_m
}
Thank you very much in advance!!
CodePudding user response:
Yes, your triple loop can be replaced with the following one-liner:
lapply(o, function(x) outer(x, x, function(a, b) as.numeric(b == 1 & a == 0)))
#> $s1
#> [,1] [,2] [,3]
#> [1,] 0 0 0
#> [2,] 1 0 0
#> [3,] 1 0 0
#>
#> $s2
#> [,1] [,2] [,3]
#> [1,] 0 1 1
#> [2,] 0 0 0
#> [3,] 0 0 0
#>
#> $s3
#> [,1] [,2] [,3]
#> [1,] 0 0 0
#> [2,] 1 0 1
#> [3,] 0 0 0
#>
#> $s4
#> [,1] [,2] [,3]
#> [1,] 0 1 1
#> [2,] 0 0 0
#> [3,] 0 0 0
CodePudding user response:
You inner for
loops are doing an outer
:
m <- lapply(o, function(x) {outer(1 - x, x)})