Переупорядочение столбцов в большом кадре данных

Используя следующий пример dataframe:

a <-  c(1:5)
b <- c("Cat", "Dog", "Rabbit", "Cat", "Dog")
c <- c("Dog", "Rabbit", "Cat", "Dog", "Dog")
d <- c("Rabbit", "Cat", "Dog", "Dog", "Rabbit")
e <- c("Cat", "Dog", "Dog", "Rabbit", "Cat")
f <- c("Cat", "Dog", "Dog", "Rabbit", "Cat")

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

Я хочу исследовать, как изменить порядок столбцов без необходимости ввода всех имен столбцов, т.е. df[,c("a","d","e","f","b","c")]

Как я могу сказать, что мне нужны столбцы b и c ПОСЛЕ столбца f? (только для ссылок на столбцы или диапазон столбцов, которые я хочу переместить?).

Большое спасибо за вашу помощь.

Ответ 1

Если вы просто перемещаете некоторые столбцы до конца, вы можете создать небольшую вспомогательную функцию, такую ​​как:

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

Я бы не рекомендовал слишком привыкать к использованию позиций столбцов, особенно не с программной точки зрения, поскольку эти позиции могут измениться.


Обновление "Для удовольствия"

Здесь расширенная интерпретация указанной функции. Он позволяет перемещать столбцы в первую или последнюю позицию или находиться перед или после другого столбца.

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
}

Попробуйте следующее:

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")

Вам нужно будет адаптировать его для проверки ошибок - например, если вы попытаетесь переместить столбцы "b" и "c" на "до c", вы, очевидно, получите ошибку.

Ответ 2

Чтобы переместить определенные столбцы в начало или конец файла data.frame, используйте select из пакета dplyr и его everything(). В этом примере мы отправляем до конца:

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

Без отрицания столбцы будут отправляться на передний план.

Ответ 3

Вы можете ссылаться на столбцы по положению. например.

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

Ответ 4

Обобщение перестановки столбцов в любом порядке с помощью dplyr, например, для перестановки:

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

к

df[,c("a","d","e","f","b","c")]

df %>% select(a, d:f, b:c)

Ответ 5

Вот еще один вариант:

df <- cbind( df[, -(2:3)], df[, 2:3] )

Ответ 6

Я изменил предыдущую функцию, чтобы использовать ее для data.table usinf для функции setcolorder таблицы данных package.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")