Search code examples
rdataframetidy

Is it possible to reorder columns in a data frame so that ABCDE is reordered to ABDCE by specifying to move D to between B and C?


Is it possible to reorder columns in a data frame so that initial order ABCDE is reordered to ABDCE by specifying that you want to move column D from its current location to between B and C?

For example, the mtcars dataset has the current order below:

mtcars <- data.frame(mtcars)
> colnames(mtcars)
 [1] "mpg"  "cyl"  "disp" "hp"   "drat" "wt"   "qsec" "vs"   "am"   "gear" "carb"

I want to move the column gear to a position between disp and hp by running code that specifically asks to move "gear" to a position between disp and hp. The result would like like below, in the data frame mtcars_reordered.

> colnames(mtcars_reordered)
 [1] "mpg"  "cyl"  "disp" "gear" "hp"   "drat" "wt"   "qsec" "vs"   "am" "carb"

This would make it easier to reorder data frames without specifying the order of all variables.

Is this possible? If so, how would it be done?


Solution

  • Try the following function.
    Argument swap is the names of the 3 columns before reordering them.

    reorder_df_cols <- function(x, swap){
      i_swap <- match(swap, names(x))
      tmp1 <- x[seq_len(i_swap[1])]
      vars <- x[rev(i_swap[-1])]
      tmp2 <- x[-c(seq_len(i_swap[1]), i_swap[-1])]
      cbind(tmp1, vars, tmp2)
    }
    
    data(mtcars, package = "datasets")
    
    swap <- c("disp", "hp", "gear")
    colnames(reorder_df_cols(mtcars, swap))
    # [1] "mpg"  "cyl"  "disp" "gear" "hp"   "drat" "wt"   "qsec" "vs"  
    #[10] "am"   "carb"