So what you want is apply order()
to each column. There's a small problem, which is that order()
will put the NA at the end, but then still give their order (while you also want their order itself to be NA). So here I wrote order_pad()
that adds back the NAs after ordering.
Then we need to paste()
the other character. I use B_char[]
to make clear that I want want to replace the content of B_char
, keeping the matrix structure.
And since paste
coerces NA
to "NA", I replaced them back.
A <- matrix(c(2,3,1,3,NA,7,1,NA,NA), nrow=3, ncol=3)
B <- matrix(c("b2", "b1", "b3", "b3", "b1", NA, "b1", NA, NA),
nrow=3, ncol=3)
order_pad <- function(x, ...){
y <- order(x, ...)
n <- length(y)
k <- sum(is.na(x))
if(k>0) y[(n-k+1):n] <- NA
y
}
# Find the order of each column
B_order <- apply(A, 2, order_pad, decreasing = TRUE)
# replace each element by that element with the character
B_char <- B_order
B_char[] <- paste0("b", B_char)
B_char[B_char == "bNA"] <- NA_character_
B_char
#> [,1] [,2] [,3]
#> [1,] "b2" "b3" "b1"
#> [2,] "b1" "b1" NA
#> [3,] "b3" NA NA
B
#> [,1] [,2] [,3]
#> [1,] "b2" "b3" "b1"
#> [2,] "b1" "b1" NA
#> [3,] "b3" NA NA
all.equal(B, B_char)
#> [1] TRUE
Created on 2021-12-20 by the reprex package (v2.0.1)