Перемещение столбцов внутри data.frame () без повторного ввода - PullRequest
52 голосов
/ 30 июля 2010

Существует ли способ перемещения столбца из одной позиции в data.frame на следующую - без ввода совершенно нового data.frame ()

Например:

a <- b <- c <- d <- e <- f <- g <- 1:100
df <- data.frame(a,b,c,d,e,f,g)

Теперь допустим, что я хотел "g" перед "a"

Я мог бы перепечатать его, как

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

Но нет ли более быстрого пути? (Представьте 1500+ столбцов)

Ответы [ 15 ]

60 голосов
/ 30 июля 2010

Функция subset имеет приятный аргумент select, который предоставляет удобный способ выбора диапазонов столбцов по имени:

df <- subset(df, select=c(g,a:f))
52 голосов
/ 30 июля 2010

Вот один из способов сделать это:

> col_idx <- grep("g", names(df))
> df <- df[, c(col_idx, (1:ncol(df))[-col_idx])]
> names(df)
[1] "g" "a" "b" "c" "d" "e" "f"
45 голосов
/ 30 августа 2013

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

Вот функция:

moveme <- function (invec, movecommand) {
  movecommand <- lapply(strsplit(strsplit(movecommand, ";")[[1]], 
                                 ",|\\s+"), function(x) x[x != ""])
  movelist <- lapply(movecommand, function(x) {
    Where <- x[which(x %in% c("before", "after", "first", 
                              "last")):length(x)]
    ToMove <- setdiff(x, Where)
    list(ToMove, Where)
  })
  myVec <- invec
  for (i in seq_along(movelist)) {
    temp <- setdiff(myVec, movelist[[i]][[1]])
    A <- movelist[[i]][[2]][1]
    if (A %in% c("before", "after")) {
      ba <- movelist[[i]][[2]][2]
      if (A == "before") {
        after <- match(ba, temp) - 1
      }
      else if (A == "after") {
        after <- match(ba, temp)
      }
    }
    else if (A == "first") {
      after <- 0
    }
    else if (A == "last") {
      after <- length(myVec)
    }
    myVec <- append(temp, values = movelist[[i]][[1]], after = after)
  }
  myVec
}

Использование просто. Попробуйте это:

moveme(names(df), "g first")
moveme(names(df), "g first; a last; e before c")

Конечно, использовать его для изменения порядка столбцов в вашем data.frame просто:

df[moveme(names(df), "g first")]

И для data.table с (перемещение по ссылке, без копии):

setcolorder(dt, moveme(names(dt), "g first"))

Основные опции:

  • последний
  • до
  • после

Составные ходы разделяются точкой с запятой.

43 голосов
/ 27 мая 2015

Используйте select из пакета dplyr и его функции everything() для перемещения определенных столбцов в начало или конец элемента данных.

Перейти к началу:

library(dplyr)
df %>%
  select(g, everything())

Перейти к концу:

df %>%
  select(-a, everything())

Или без оператора %>%, это были бы select(df, g, everything()) и select(df, -a, everything()) соответственно.

8 голосов
/ 28 августа 2014

Вот мое решение

df[c(7,1:6)]

или вы также можете изменить порядок по имени столбца:

df[c("g",names(df)[-7])]
1 голос
/ 09 ноября 2017

Это очень старый пост, но я разработал этот код, который динамически меняет положение столбца в кадре данных.Просто измените значение n и имя столбца (здесь «g») и получите фрейм данных с новым расположением столбцов.

df1 = subset(df, select = c(head(names(df),n=3),"g", names(df) [! names(df) %in% c(head(names(df),n=3),"g")]))
1 голос
/ 29 июня 2016

Вот аналогичный способ, которым я использовал для перемещения n-го столбца на 2-ю позицию в огромном фрейме данных на основе имени столбца.

Перемещение столбца на первую позицию:

## Move a column with name "col_name"  to first column 
colX <- grep("^col_name", colnames(df.original)) 
# get the column position from name 

df.reordered.1 <- df.original[,c(colX,1:(colX-1), (colX+1):length(df.original))]  
# get new reordered data.frame
# if the column is the last one, error "undefined columns selected" will show up. Then do the following command instead of this

df.reordered.1 <- df.original[,c(colX,1:(colX-1)]  
# get new reordered data.frame, if the column is the last one

От куда угодно до 'n' позиции

## Move a column with name "col_name"  to column position "n", 
## where n > 1 (in a data.frame "df.original")

colX <- grep("^col_name", colnames(df.original)) 
# get the column position from name 

n <- 2 
# give the new expected column position (change to the position you need) 

df.reordered.2 <- df.original[,c(1:(n-1), colX, n:(colX-1), (colX+1):length(df.original))] 
# get new reordered data.frame

## Optional; to replace the original data frame with sorted data.frame 
## if the sorting looks good
df.original <- df.reordered.2
rm(df.reordered.2) # remove df
1 голос
/ 31 октября 2015

Это немного более элегантно и позволяет расположить первые несколько крайних левых столбцов, а остальные - без правых.

0 голосов
/ 28 августа 2018

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

У вас есть следующие имена столбцов: "a", "b", "c", "d", "e", "f", "g", "h", "i", "j"

Переместить «d» во вторую позицию (после «a»):

attach(df)

df <- cbind(a, d, df[,c(2:3,5:10)])

Переместить «j» на 4-ю позицию (после «c»):

df <- cbind(df[,c(1:3)], j, df[,c(4:9)])
0 голосов
/ 28 марта 2018

Большинство решений кажутся слишком многословными или лишены инкапсуляции.Вот еще один способ решения проблемы

push_left <- function(df, pushColNames){
    df[, c(pushColNames, setdiff(names(df), pushColNames))]
}

push_left(iris, c("Species", "Sepal.Length"))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...