Перемещение столбцов в data.frame () без повторного набора

Есть ли способ перемещения столбца из одной позиции в 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+ столбцов)

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

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

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

 df <- subset(df, select=c(g,a:f)) 

Я написал эту функцию, недавно названную 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 столбцов в вашем data.frame является простым:

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

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

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

Основные параметры:

  • первый
  • последний
  • до
  • после

Смешанные перемещения разделяются точкой с запятой.

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

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

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

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

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

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

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

 df[c(7,1:6)] 

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

 df[c("g",names(df)[-7])] 

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

 ordered_columns_leftside=c('var10','var34','var8') df=df[c(ordered_columns_leftside, setdiff(names(df),ordered_columns_leftside))] 

Аналогичным образом я использовал, чтобы переместить 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 

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

 df1 = subset(df, select = c(head(names(df),n=3),"g", names(df) [! names(df) %in% c(head(names(df),n=3),"g")])) 

Если переупорядочение является сдвигом, как в вашем примере, вы можете использовать функцию shift из пакета taRifx . Он действует на векторы, поэтому применяет его к именам столбцов:

 > a <- b <- c <- d <- e <- f <- g <- 1:5 > df <- data.frame(a,b,c,d,e,f,g) > df[, taRifx::shift(seq_along(df),-1)] gabcdef 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 

Фактически функция shift также может применяться к кадру данных, но не так, как ожидалось. Вы можете написать функцию:

 > shift_df <- function(df, n) df[, taRifx::shift(seq_along(df),n)] > shift_df(df, -1) gabcdef 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 > shift_df(df, 2) cdefgab 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 

Я хотел бы внести еще один универсальный рабочий подход, похожий на предыдущие ответы rcs, Manuel и Scott Kaiser, которые работают только в конкретных случаях:

 move<-function(new.pos,nameofcolumn,dfname) { col_idx <- grep(nameofcolumn, names(dfname)) if (length(col_idx)==0){print("invalid column name")} else { if(new.pos>ncol(dfname)){print("invalid column number")} else { if (new.pos==1) { b<-dfname[ , c( col_idx, c((new.pos):ncol(dfname))[-(abs(new.pos-1-col_idx))] )] } else if(col_idx==1 & new.pos==ncol(dfname)){ b<-dfname[ , c((1:(new.pos-1)+1), col_idx )] } else if(col_idx==1){ b<-dfname[ , c((1:(new.pos-1)+1), col_idx, c((new.pos+1):ncol(dfname)) )] } else if(new.pos==ncol(dfname)){ b<-dfname[ , c((1:(new.pos))[-col_idx], col_idx)] } else if(new.pos>col_idx){ b<-dfname[ , c((1:(new.pos))[-col_idx], col_idx, c((new.pos+1):ncol(dfname)) )] } else{ b<-dfname[ , c((1:(new.pos-1)), col_idx, c((new.pos):ncol(dfname))[-(abs(new.pos-1-col_idx))] )] } return(b) if(length(ncol(b))!=length(ncol(dfname))){print("error")} } }} 

Применение:

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

Вот простая, но гибкая функция, которую я написал для перемещения столбца в любом месте в фрейме данных.

 move.col <- function(df, move_this, next_to_this, before = FALSE) { if (before==FALSE) df[,c(match(setdiff(names(df)[1:which(names(df)==next_to_this)],move_this),names(df)), match(move_this,names(df)), match(setdiff(names(df)[which(names(df)==next_to_this):ncol(df)],c(next_to_this,move_this)),names(df)))] else df[,c(match(setdiff(names(df)[1:(which(names(df)==next_to_this))],c(next_to_this,move_this)),names(df)), match(move_this,names(df)), match(setdiff(names(df)[(which(names(df)==next_to_this)):ncol(df)],move_this),names(df)))] } 

Использование: укажите фрейм данных ( df ), имя столбца, которое вы хотите переместить ( move_this ), и имя столбца, которое вы хотите переместить рядом ( next_to_this ). По умолчанию функция будет перемещать столбец move_this после столбца next_to_this . Вы можете указать before = TRUE для перемещения move_this перед next_to_this .

Примеры:

  1. Переместить «b» после «g» (т. Е. Сделать последний столбец «b»).

move.col(df, "b", "g")

  1. Переместите «c» после «e».

move.col(df, "c", "e")

  1. Переместите «g» перед «a» (т. Е. Сделайте первый столбец «g»).

move.col(df, "g", "a", before=TRUE)

  1. Переместите «d» и «f» перед «b» (т. Е. Переместите несколько столбцов).

move.col(df,c("d","f"),"b", before=TRUE)

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

 push_left <- function(df, pushColNames){ df[, c(pushColNames, setdiff(names(df), pushColNames))] } push_left(iris, c("Species", "Sepal.Length")) 

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

У вас есть следующие имена столбцов: «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)]) 

Вот одна из функций, которая может помочь

  • Данные : блок данных
  • ColName : имя столбца (столбцов), подлежащего перемещению
  • Позиция : номер столбца, в котором вы хотите, чтобы столбец перемещался

 moveCol <- function(Data,ColName,Position=1) { D <- dim(Data)[2] DFnames <- names(Data) if (Position>D+1 | Position<1) { warning(paste0('Column position ',sprintf('%d',Position), ' is out of range [1-',sprintf('%d',D),']')) return } for (i in seq(length(ColName))) { colName <- ColName[i] x <- colName==DFnames if (all(!x)) { warning(paste0('Tag \"', colName, '\" not found')) } else { D1 <- seq(D) D1[x] = Position - 0.5 Data <- Data[order(D1)] } } return(Data) } 

@ Дэвид спросил, как переместить «G» на произвольную позицию, например 4. Настроить ответ @rcs,

 new.pos <- 4 col_idx <- grep("g", names(df)) df <- df[ , c((1:new.pos)[-col_idx], col_idx, c((new.pos):ncol(df))[-col_idx])] 
  • Тест anova терпит неудачу на lme fits, созданный с помощью вставленной формулы
  • Добавить столбец «ранг» в кадр данных
  • Для каждой строки возвращаем имя столбца наибольшего значения
  • Возьмите сумму переменной, если комбинация значений в двух других столбцах уникальна
  • Как увидеть исходный код функции R .Internal или .Primitive?
  • Импорт CSV-файла в R-числовые значения, считанные как символы
  • Добавить столбец с подсчетами другого
  • Вычислить разницу между значениями в последовательных строках по группам
  • Лучший способ конвертировать список в вектор?
  • Ускорение производительности write.table
  • Прочтите файл csv в R со столбцом валюты как числовой
  • Давайте будем гением компьютера.