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

如何改变这个input(顺序:时间,进出,文件):

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

到这个输出(与序列:时间,出,在,文件)?

 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 

你的数据框有四个像df[,c(1,2,3,4)]这样的列。 注意第一个逗号意味着保留所有的行,1,2,3,4指向列。

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

如果你想输出这个文件为csv,请执行write.csv(df2, file="somedf.csv")

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

你也可以使用子集函数:

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

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

更新:

您也可以使用dplyr软件包中的selectfunction:

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

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

 mtcars %>% select(carb:mpg) 

下面将重新排列一些列,并丢弃其他列:

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

阅读更多关于dplyr的select语法 。

正如在这个评论中提到的那样,对data.frame中的列进行重新sorting的标准build议通常很麻烦,而且容易出错,特别是如果你有很多列的话。

此function允许按位置重新排列列:指定variables名称和所需的位置,不要担心其他列。

 ##arrange df vars by position ##'vars' must be a named vector, eg 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 

也许这是巧合的,你想要的列顺序碰巧有按降序字母顺序列名称。 既然如此,你可以这样做:

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

当我有大量文件的列时,这就是我所使用的。

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

如何重新sortingdata.table列(不复制)

 setcolorder(DT,myOrder) 

我见过的唯一工作就是从这里开始 。

  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 } 

像这样使用:

 new_df <- iris[shuffle_columns(names(iris), "Sepal.Width before Sepal.Length")] 

奇迹般有效。