Search code examples
rdplyr

Order variable names by custom numeric pattern


I have the following dataset:

df <- structure(list(a3_1_1 = 0, a3_1_2 = 0, a3_1_3 = 0, a3_1_4 = 0, 
    a3_1_5 = 0, a3_1_6 = 0, a3_1_7 = 0, a3_1_8 = 0, a3_1_9 = 0, 
    a3_1_10 = 0, a3_1_11 = 0, a3_1_12 = 0, a3_1_13 = 0, a3_1_14 = 0, 
    a3_1_15 = 0, a3_1_16 = 0, a3_1_17 = 0, a3_2_1 = 0, a3_2_2 = 0, 
    a3_2_3 = 0, a3_2_4 = 0, a3_2_5 = 0, a3_2_6 = 0, a3_2_7 = 0, 
    a3_2_8 = 0, a3_2_9 = 0, a3_2_10 = 0, a3_2_11 = 0, a3_2_12 = 0, 
    a3_2_13 = 0, a3_2_14 = 0, a3_2_15 = 0, a3_2_16 = 0, a3_2_17 = 0, 
    a3_3_1 = 0, a3_3_2 = 0, a3_3_3 = 0, a3_3_4 = 0, a3_3_5 = 0, 
    a3_3_6 = 0, a3_3_7 = 0, a3_3_8 = 0, a3_3_9 = 0, a3_3_10 = 0, 
    a3_3_11 = 0, a3_3_12 = 0, a3_3_13 = 0, a3_3_14 = 0, a3_3_15 = 0, 
    a3_3_16 = 0, a3_3_17 = 0), row.names = c(NA, -1L), class = "data.frame")

I have many variables that are part of a table with the same variable name's number pattern. I'm looking for a certain arrangement: the second number should be arranged as a group inside the last number. That way, I would like to make a function that takes the first and the last variable as arguments and arranges them in such a way. The desired output should be this:

ordered_df <- structure(list(a3_1_1 = 0, a3_2_1 = 0, a3_3_1 = 0, a3_1_2 = 0, 
    a3_2_2 = 0, a3_3_2 = 0, a3_1_3 = 0, a3_2_3 = 0, a3_3_3 = 0, 
    a3_1_4 = 0, a3_2_4 = 0, a3_3_4 = 0, a3_1_5 = 0, a3_2_5 = 0, 
    a3_3_5 = 0, a3_1_6 = 0, a3_2_6 = 0, a3_3_6 = 0, a3_1_7 = 0, 
    a3_2_7 = 0, a3_3_7 = 0, a3_1_8 = 0, a3_2_8 = 0, a3_3_8 = 0, 
    a3_1_9 = 0, a3_2_9 = 0, a3_3_9 = 0, a3_1_10 = 0, a3_2_10 = 0, 
    a3_3_10 = 0, a3_1_11 = 0, a3_2_11 = 0, a3_3_11 = 0, a3_1_12 = 0, 
    a3_2_12 = 0, a3_3_12 = 0, a3_1_13 = 0, a3_2_13 = 0, a3_3_13 = 0, 
    a3_1_14 = 0, a3_2_14 = 0, a3_3_14 = 0, a3_1_15 = 0, a3_2_15 = 0, 
    a3_3_15 = 0, a3_1_16 = 0, a3_2_16 = 0, a3_3_16 = 0, a3_1_17 = 0, 
    a3_2_17 = 0, a3_3_17 = 0), row.names = c(NA, -1L), class = "data.frame")

The solution I'm looking for should use dplyr::arrange, but I'm obviously open to suggestions.

my_arranger <- function(df, from = col1, to = col2){
df %>% arrange({{col1}}:{{col2}}) #Here should make the above requested arrangement
}

Solution

  • You can try the code below

    nms <- names(df)
    
    d2 <- as.integer(gsub(".*_(\\d+)_.*", "\\1", nms))
    d3 <- as.integer(gsub(".*_(\\d+)$", "\\1", nms))
    
    nms[order(d3, d2)]