Search code examples
rfunctiondplyrtidyversetibble

Re-ordering a symmetric tibble


Imagine we have a tibble like shown below. In theory, the first column acts simply a rownames that must have one-on-one correspondence with the columns' names.

For example, excluding the first column (row_name), the third column from the left is named G, but the the corresponding row is E.

I was wondering how we could re-order the rows (e.g., bring up row titled G two rows up) so the rows and columns match?

out <- tibble(row_name=factor(c("A","B","E","F","G")),`A`=as.character(1:5),`B`=as.character(c(2,NA,0:2)),
`G`=as.character(4:8),`E`=as.character(4:8),`F`=as.character(4:8))


#  row_name A     B     G     E     F    
#  <fct>    <chr> <chr> <chr> <chr> <chr>
#1 A        1     2     4     4     4    
#2 B        2     NA    5     5     5    
#3 E        3     0     6     6     6    
#4 F        4     1     7     7     7    
#5 G        5     2     8     8     8


# EXPECTED OUTPUT:

#  row_name A     B     G     E     F    
#  <fct>    <chr> <chr> <chr> <chr> <chr>
#1 A        1     2     4     4     4    
#2 B        2     NA    5     5     5
#5 G        5     2     8     8     8
#3 E        3     0     6     6     6    
#4 F        4     1     7     7     7   

Solution

  • If we want to reorder the rows, use match within slice

    library(dplyr)
    out %>%
       slice(match(names(.)[-1], row_name))
    

    -output

    # A tibble: 5 x 6
      row_name A     B     G     E     F    
      <fct>    <chr> <chr> <chr> <chr> <chr>
    1 A        1     2     4     4     4    
    2 B        2     <NA>  5     5     5    
    3 G        5     2     8     8     8    
    4 E        3     0     6     6     6    
    5 F        4     1     7     7     7  
    

    Or within arrange

    out %>% 
        arrange(factor(row_name, levels = names(.)[-1]))
    

    -output

    # A tibble: 5 x 6
      row_name A     B     G     E     F    
      <fct>    <chr> <chr> <chr> <chr> <chr>
    1 A        1     2     4     4     4    
    2 B        2     <NA>  5     5     5    
    3 G        5     2     8     8     8    
    4 E        3     0     6     6     6    
    5 F        4     1     7     7     7