在data.frame()中移动列而无需重新输入

时间:2010-07-30 08:52:42

标签: r

是否有一种方法可以将列从data.frame中的一个位置移动到下一个位置 - 而无需键入全新的data.frame()

例如:

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

现在让我们说我想在“a”前面加上“g”

我可以重新输入它,如

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

但是没有更快的方法吗? (想象一下1500+列)

17 个答案:

答案 0 :(得分:58)

subset函数有一个很好的select参数,可以方便地按名称选择列范围:

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

答案 1 :(得分:52)

这是一种方法:

> 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 :(得分:43)

我最近写了这个函数叫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 s(按引用移动,不复制):

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

基本选项是:

  • 第一
  • 最后
  • 之后

复合移动用分号分隔。

答案 3 :(得分:42)

使用dplyr软件包及其select函数中的everything()将特定列移至data.frame的开头或结尾。

转到开头:

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

移到最后:

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

如果没有%>%管道运算符,则分别为select(df, g, everything())select(df, -a, everything())

答案 4 :(得分:8)

这是我的解决方案

df[c(7,1:6)]

或者您也可以按列名重新排序:

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

答案 5 :(得分:2)

使用relocate包中的dplyr

mtcars %>% 
   # dplyr::relocate(disp) %>% ## simply make disp the first column
   relocate(starts_with("c"), .after = disp)  %>% ## more complex column order shuffling
   head(3)

请注意,该功能是在1.0版中添加的,请参见https://www.tidyverse.org/blog/2020/03/dplyr-1-0-0-select-rename-relocate/

答案 6 :(得分:1)

对于data.table用户:

使用setcolorder()

setDT(df) # convert into data.table

setcolorder(df,'g') # column g comes first if not all column names are mentioned
setcolorder(df, 7)  # same as above

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
  4:   4   4   4   4   4   4   4
  5:   5   5   5   5   5   5   5
  6:   6   6   6   6   6   6   6
  7:   7   7   7   7   7   7   7

如果应将列“ a”和“ b”移到最右边:

setcolorder(df,3:7) 
df

       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
  6:   6   6   6   6   6   6   6
  7:   7   7   7   7   7   7   7

答案 7 :(得分:1)

这是一篇非常古老的帖子,但我开发了这段代码,可以动态更改数据框中的列位置。只需更改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")]))

答案 8 :(得分:1)

这里的方法类似于我根据列名将第#列移到第二个位置的大数据框中。

将列移至第一个位置:

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

答案 9 :(得分:1)

This is slightly more elegant and allows to arrange first few leftmost columns and leave the rest unarranged to the right.

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

答案 10 :(得分:0)

我想提供另一种普遍的工作方法,类似于以前的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)

答案 11 :(得分:0)

这是一个简单但灵活的函数,我写的是在数据框中的任何位置移动列。

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)。默认情况下,该函数会在<{em> move_this列之后移动next_to_this。您可以指定before = TRUEmove_this之前移动next_to_this

<强>示例:

  1. 移动&#34; b&#34;之后&#34; g&#34; (即,制作&#34; b&#34;最后一栏)。
  2. move.col(df, "b", "g")

    1. 移动&#34; c&#34;在&#34; e&#34;。
    2. 之后

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

      1. 移动&#34; g&#34;之前&#34; a&#34; (即,制作&#34; g&#34;第一栏)。
      2. move.col(df, "g", "a", before=TRUE)

        1. 移动&#34; d&#34;和&#34; f&#34;之前&#34; b&#34; (即移动多列)。
        2. move.col(df,c("d","f"),"b", before=TRUE)

答案 12 :(得分:0)

大多数解决方案看起来过于冗长或缺乏封装。这是解决问题的另一种方法

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

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

答案 13 :(得分:0)

我找到了一种非常简单的方法来满足我的需要,并且不需要很多时间。

您具有以下列名称:“ a”,“ b”,“ c”,“ d”,“ e”,“ f”,“ g”,“ h”,“ i”,“ j” < / p>

将“ 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 :(得分:0)

如果重新排序是一个转变,就像在您的示例中一样,您可以使用from a import aa 包中的pip install weasyprint python >>> pdf = weasyprint.HTML('http://www.google.com').write_pdf() >>> len(pdf) 92059 >>> file('google.pdf', 'w').write(pdf) 函数。它作用于向量,因此将其应用于列名:

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

答案 15 :(得分:-1)

这是一个可能有用的功能

  • 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 :(得分:-2)

@David询问如何移动&#34; G&#34;到任意位置,例如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])]