Подтвердить что ты не робот

Перемещение столбцов в 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 + столбцов)

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

Ответ 3

Я недавно написал эту функцию под названием 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"))

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

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

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

Ответ 4

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

Переместить в начало:

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

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

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

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

Ответ 5

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

df[c(7,1:6)]

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

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

Ответ 6

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

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

Ответ 7

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

Ответ 8

Это очень старое сообщение, но я разработал этот код, который динамически меняет положение столбца в кадре данных. Просто измените значение 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")]))

Ответ 9

Если переупорядочение является сдвигом, как в вашем примере, вы можете использовать функцию 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)]
  g a b c d e f
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)
  g a b c d e f
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)
  c d e f g a b
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

Ответ 10

Я хотел бы предложить другой универсальный рабочий подход, аналогичный предыдущим ответам rcs, Мануэля и Скотта Кайзера, который работает только в определенных случаях:

move<-function(new.pos,nameofcolumn,dfname) {
  col_idx <- grep(nameofcolumn, names(dfname))
  if (length(col_idx)==0){print("invalid column name");return(dfname)} else {
  if(new.pos>ncol(dfname)){print("invalid column number");return(dfname)} 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)

Ответ 11

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

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. Переместите "с" после "е".

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)

Ответ 12

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

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

push_left(iris, c("Species", "Sepal.Length"))

Ответ 13

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

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

Ответ 14

Из data.table 1.11.0 вы можете использовать setcolorder (" setcolorder() теперь принимает меньше ncol(DT) столбцов для перемещения вперед"):

setDT(df)
setcolorder(df, "g")
df
df
#     g  a  b  c  d  e  f
# 1:  1  1  1  1  1  1  1
# 2:  2  2  2  2  2  2  2
# 3:  3  3  3  3  3  3  3
# ...snip...

Ответ 15

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

  • df: датафрейм
  • ColName: имя столбца (столбцов), который нужно переместить
  • Позиция: номер столбца, который вы хотите, чтобы появился перемещенный столбец

moveCol <- function(df,ColName,Position=1) {
    D <- dim(df)[2]
    DFnames <- names(df)
    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 ColName) {
        x <- i==DFnames
        if (all(!x)) {
            warning(paste0('Column \"', i, '\" not found'))
        } else {
            D1 <- seq(D)
            D1[x] = Position - 0.5
            df<- df[order(D1)]
        }
    }
    return(df)
}

Ответ 16

@Дэвид спросил, как переместить "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])]