Reordering columns in a large dataframe

前端 未结 8 719
感动是毒
感动是毒 2020-12-12 21:25

Using the following example dataframe:

a <-  c(1:5)
b <- c(\"Cat\", \"Dog\", \"Rabbit\", \"Cat\", \"Dog\")
c <- c(\"Dog\", \"Rabbit\", \"Cat\", \"Do         


        
相关标签:
8条回答
  • 2020-12-12 22:07

    To move specific columns to the beginning or end of a data.frame, use select from the dplyr package and its everything() function. In this example we are sending to the end:

    library(dplyr)
    df %>%
      select(-b, -c, everything())
    
      a      d      e      f      b      c
    1 1 Rabbit    Cat    Cat    Cat    Dog
    2 2    Cat    Dog    Dog    Dog Rabbit
    3 3    Dog    Dog    Dog Rabbit    Cat
    4 4    Dog Rabbit Rabbit    Cat    Dog
    5 5 Rabbit    Cat    Cat    Dog    Dog
    

    Without the negation, the columns would be sent to the front.

    0 讨论(0)
  • 2020-12-12 22:08

    I changed the previous function to use it for data.table usinf the function setcolorder of the package data.table.

    moveMeDataTable <-function(data, tomove, where = "last", ba = NULL) {
      temp <- setdiff(names(data), tomove)
      x <- switch(
        where,
        first = setcolorder(data,c(tomove, temp)),
        last = setcolorder(data,c(temp, tomove)),
        before = {
          if (is.null(ba)) stop("must specify ba column")
          if (length(ba) > 1) stop("ba must be a single character string")
          order = append(temp, values = tomove, after = (match(ba, temp)-1))
          setcolorder(data,order)
    
        },
        after = {
          if (is.null(ba)) stop("must specify ba column")
          if (length(ba) > 1) stop("ba must be a single character string")
          order = append(temp, values = tomove, after = (match(ba, temp)))
          setcolorder(data,order)
        })
      x
    }
    
    DT <- data.table(A=sample(3, 10, TRUE),
                    B=sample(letters[1:3], 10, TRUE), C=sample(10))
    DT <- moveMeDataTable(DT, "C", "after", "A")
    
    0 讨论(0)
  • 2020-12-12 22:11

    To generalize the reshuffling of columns in any order using dplyr, for example, to reshuffle:

    df <- data.frame(a,b,c,d,e,f)
    

    to

    df[,c("a","d","e","f","b","c")]
    
    df %>% select(a, d:f, b:c)
    
    0 讨论(0)
  • 2020-12-12 22:14

    Here is another option:

    df <- cbind( df[, -(2:3)], df[, 2:3] )
    
    0 讨论(0)
  • 2020-12-12 22:19

    You can refer to columns by position. e.g.

    df <- df[ ,c(1,4:6,2:3)]
    > df
      a      d      e      f      b      c
    1 1 Rabbit    Cat    Cat    Cat    Dog
    2 2    Cat    Dog    Dog    Dog Rabbit
    3 3    Dog    Dog    Dog Rabbit    Cat
    4 4    Dog Rabbit Rabbit    Cat    Dog
    5 5 Rabbit    Cat    Cat    Dog    Dog
    
    0 讨论(0)
  • 2020-12-12 22:22

    If you're just moving certain columns to the end, you can create a little helper-function like the following:

    movetolast <- function(data, move) {
      data[c(setdiff(names(data), move), move)]
    }
    
    movetolast(df, c("b", "c"))
    #   a      d      e      f      b      c
    # 1 1 Rabbit    Cat    Cat    Cat    Dog
    # 2 2    Cat    Dog    Dog    Dog Rabbit
    # 3 3    Dog    Dog    Dog Rabbit    Cat
    # 4 4    Dog Rabbit Rabbit    Cat    Dog
    # 5 5 Rabbit    Cat    Cat    Dog    Dog
    

    I would not recommend getting too into the habit of using column positions, especially not from a programmatic standpoint, since those positions might change.


    "For fun" update

    Here's an extended interpretation of the above function. It allows you to move columns to either the first or last position, or to be before or after another column.

    moveMe <- function(data, tomove, where = "last", ba = NULL) {
      temp <- setdiff(names(data), tomove)
      x <- switch(
        where,
        first = data[c(tomove, temp)],
        last = data[c(temp, tomove)],
        before = {
          if (is.null(ba)) stop("must specify ba column")
          if (length(ba) > 1) stop("ba must be a single character string")
          data[append(temp, values = tomove, after = (match(ba, temp)-1))]
        },
        after = {
          if (is.null(ba)) stop("must specify ba column")
          if (length(ba) > 1) stop("ba must be a single character string")
          data[append(temp, values = tomove, after = (match(ba, temp)))]
        })
      x
    }
    

    Try it with the following.

    moveMe(df, c("b", "c"))
    moveMe(df, c("b", "c"), "first")
    moveMe(df, c("b", "c"), "before", "e")
    moveMe(df, c("b", "c"), "after", "e")
    

    You'll need to adapt it to have some error checking--for instance, if you try to move columns "b" and "c" to "before c", you'll (obviously) get an error.

    0 讨论(0)
提交回复
热议问题