如何重新排序数据框中的列?

时间:2011-04-11 11:55:14

标签: r sorting dataframe

如何更改此输入(使用序列:time,in,out,files):

Time   In    Out  Files
1      2     3    4
2      3     4    5

到此输出(顺序为:time,out,in,files)?

Time   Out   In  Files
1      3     2    4
2      4     3    5

这是虚拟R数据:

table <- data.frame(Time=c(1,2), In=c(2,3), Out=c(3,4), Files=c(4,5))
table
##  Time In Out Files
##1    1  2   3     4
##2    2  3   4     5

11 个答案:

答案 0 :(得分:280)

您的数据框有四列,如df[,c(1,2,3,4)]。 请注意,第一个逗号表示保留所有行,1,2,3,4表示列。

要更改上述问题,请执行df2[,c(1,3,2,4)]

如果要将此文件作为csv输出,请执行write.csv(df2, file="somedf.csv")

答案 1 :(得分:139)

# reorder by column name
data <- data[c("A", "B", "C")]

#reorder by column index
data <- data[c(1,3,2)]

答案 2 :(得分:84)

您还可以使用子集函数:

data <- subset(data, select=c(3,2,1))

您应该在其他答案中更好地使用[]运算符,但知道您可以在单个命令中执行子集和列重新排序操作可能很有用。

更新

您也可以使用dplyr包中的select函数:

data = data %>% select(Time, out, In, Files)

我不确定效率,但是由于dplyr的语法,这个解决方案应该更灵活,特别是如果你有很多专栏。例如,以下内容将按相反的顺序对mtcars数据集的列重新排序:

mtcars %>% select(carb:mpg)

以下内容将仅对某些列重新排序,并丢弃其他列:

mtcars %>% select(mpg:disp, hp, wt, gear:qsec, starts_with('carb'))

详细了解dplyr's select syntax

答案 3 :(得分:33)

正如this comment中所述,在data.frame中重新排序列的标准建议通常很麻烦且容易出错,尤其是如果您有很多列。

此功能允许按位置重新排列列:指定变量名称和所需位置,而不必担心其他列。

##arrange df vars by position
##'vars' must be a named vector, e.g. c("var.name"=1)
arrange.vars <- function(data, vars){
    ##stop if not a data.frame (but should work for matrices as well)
    stopifnot(is.data.frame(data))

    ##sort out inputs
    data.nms <- names(data)
    var.nr <- length(data.nms)
    var.nms <- names(vars)
    var.pos <- vars
    ##sanity checks
    stopifnot( !any(duplicated(var.nms)), 
               !any(duplicated(var.pos)) )
    stopifnot( is.character(var.nms), 
               is.numeric(var.pos) )
    stopifnot( all(var.nms %in% data.nms) )
    stopifnot( all(var.pos > 0), 
               all(var.pos <= var.nr) )

    ##prepare output
    out.vec <- character(var.nr)
    out.vec[var.pos] <- var.nms
    out.vec[-var.pos] <- data.nms[ !(data.nms %in% var.nms) ]
    stopifnot( length(out.vec)==var.nr )

    ##re-arrange vars by position
    data <- data[ , out.vec]
    return(data)
}

现在OP的请求变得如此简单:

table <- data.frame(Time=c(1,2), In=c(2,3), Out=c(3,4), Files=c(4,5))
table
##  Time In Out Files
##1    1  2   3     4
##2    2  3   4     5

arrange.vars(table, c("Out"=2))
##  Time Out In Files
##1    1   3  2     4
##2    2   4  3     5

要另外交换TimeFiles列,您可以执行此操作:

arrange.vars(table, c("Out"=2, "Files"=1, "Time"=4))
##  Files Out In Time
##1     4   3  2    1
##2     5   4  3    2

答案 4 :(得分:24)

这可能是一个巧合,您想要的列顺序恰好按字母顺序降序排列。既然如此,你可以做到:

df<-df[,order(colnames(df),decreasing=TRUE)]

当我拥有包含许多列的大型文件时,我使用的是什么。

答案 5 :(得分:15)

如果你可以使用data.table包,那么这提供了一种良好而紧凑的方式

How to reorder data.table columns (without copying)

setcolorder(DT,myOrder)

答案 6 :(得分:14)

select解决方案是使用select(table, "Time", "Out", "In", "Files") # or select(table, Time, Out, In, Files)

{{1}}

答案 7 :(得分:9)

dplyr版本1.0.0包含relocate()函数,可轻松对列进行重新排序:

dat <- data.frame(Time=c(1,2), In=c(2,3), Out=c(3,4), Files=c(4,5))

library(dplyr) # from version 1.0.0 only

dat %>%
  relocate(Out, .before = In)

dat %>%
  relocate(Out, .after = Time)

答案 8 :(得分:6)

three top-rated answers有弱点。

如果您的数据框看起来像这样

df <- data.frame(Time=c(1,2), In=c(2,3), Out=c(3,4), Files=c(4,5))

> df
  Time In Out Files
1    1  2   3     4
2    2  3   4     5

那么使用

是一个糟糕的解决方案
> df2[,c(1,3,2,4)]

它完成了这项工作,但您刚刚介绍了对输入中列的顺序的依赖。

应该避免这种脆弱的编程风格。

列的显式命名是更好的解决方案

data[,c("Time", "Out", "In", "Files")]

另外,如果您打算在更一般的设置中重复使用代码,则可以简单地

out.column.name <- "Out"
in.column.name <- "In"
data[,c("Time", out.column.name, in.column.name, "Files")]

这也很好,因为它完全隔离了文字。相反,如果您使用dplyr&#39; s select

data <- data %>% select(Time, out, In, Files)

然后你会设置那些稍后会自己阅读你的代码的人,包括你自己的一些欺骗行为。列名被用作文字而不会出现在代码中。

答案 9 :(得分:1)

我见过的唯一一个效果很好的是来自here

from collections import defaultdict
class TrieNode:
    def __init__(self):
        self.children = defaultdict(TrieNode)
        self.isEnd = False
    def insert(self, word):
        node = self
        for w in word:
            node = node.children[w]
        node.isEnd = True
    def find_prefix(self, prefix, result):
        if self.isEnd:
            result.append(prefix[:])
            return
        for k,v in self.children.items():
            prefix.append(k)
            v.find_prefix(prefix, result)
            prefix.pop(-1)

if __name__ == "__main__":
    words = ['foo', 'foog', 'food', 'asdf']
    root = TrieNode()
    for w in words:
        root.insert(w)
    result = []
    root.find_prefix([], result)
    print result

像这样使用:

 shuffle_columns <- 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
}

像魅力一样工作。

答案 10 :(得分:1)

setcolorder(table, c("Out", "in", "files"))