Reorder matrix columns based on colnames suffix and the order of a character vector

95 Views Asked by At

I have a matrix that looks like this

cols <- c("foo_AFG", "baz_SYR", "baz_TUR", "foo_SYR", "foo_TUR", "baz_AFG")
foo <- matrix(ncol = length(cols))
colnames(foo) <- cols
w <- c("SYR", "AFG", "TUR")

foo

     foo_AFG baz_SYR baz_TUR foo_SYR foo_TUR baz_AFG
[1,]      NA      NA      NA      NA      NA      NA

I would like to reorder the columns of foo so that the suffix of their names resembles the order of w. I only care about the suffixes (all that comes after the "_" separator).

Examples of what I want (and one of what I DON'T want):

# this is OK
     foo_SYR baz_SYR baz_AFG foo_AFG foo_TUR baz_TUR
[1,]      NA      NA      NA      NA      NA      NA

# this is OK
     baz_SYR foo_SYR baz_AFG foo_AFG baz_TUR foo_TUR
[1,]      NA      NA      NA      NA      NA      NA

# this is NOT OK
     foo_SYR foo_AFG foo_TUR baz_SYR baz_AFG baz_TUR
[1,]      NA      NA      NA      NA      NA      NA

2

There are 2 best solutions below

1
Maël On BEST ANSWER

You can create an ordered factor only based on the suffix part (extracted with gsub), and use order + [ to arrange the columns.

ord_fac <- ordered(gsub(".*_", "", colnames(foo)), levels = w)
foo[, order(ord_fac)]

#   baz_SYR foo_SYR foo_AFG baz_AFG baz_TUR foo_TUR
# 1      NA      NA      NA      NA      NA      NA
1
Darren Tsai On

You can use match() + order():

foo[, order(match(sub(".*_", "", colnames(foo)), w))]

# baz_SYR foo_SYR foo_AFG baz_AFG baz_TUR foo_TUR 
#      NA      NA      NA      NA      NA      NA