Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 如何对数据帧中的列重新排序?_R_Sorting_Dataframe_R Faq - Fatal编程技术网

R 如何对数据帧中的列重新排序?

R 如何对数据帧中的列重新排序?,r,sorting,dataframe,r-faq,R,Sorting,Dataframe,R Faq,如何更改此输入(按顺序:时间、输入、输出、文件): 该输出(顺序为:超时、超时、输入、文件) 以下是虚拟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 table您的数据帧有四列,如sodf[,c(1,2,3,4)]。 注意,第一个逗号表示保留

如何更改此输入(按顺序:时间、输入、输出、文件):

该输出(顺序为:超时、超时、输入、文件)


以下是虚拟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

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

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

如果要将此文件输出为csv,请按列名重新排序
data您还可以使用subset函数:

data <- subset(data, select=c(3,2,1))
我不确定它的效率,但是由于dplyr的语法,这个解决方案应该更灵活,特别是如果你有很多列的话。例如,以下内容将按相反顺序重新排列mtcars数据集的列:

mtcars %>% select(carb:mpg)
以下内容将仅对某些列重新排序,并放弃其他列:

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

阅读更多信息。

也许您想要的列顺序恰好有按字母降序排列的列名,这是巧合。既然是这样,你可以这样做:

df<-df[,order(colnames(df),decreasing=TRUE)]
df您可以使用该软件包:

如中所述,对
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)
}
此函数允许按位置重新排列列:指定变量名和所需位置,不必担心其他列

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

我所见过的唯一一个工作出色的是来自

shuffle\u columns解决方案(tidyverse
套装的一部分)是使用:

他们有一个弱点

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

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
它完成了这项工作,但您刚刚引入了对输入中列顺序的依赖

要避免这种脆弱的编程风格

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

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
版本
1.0.0
包括
relocate()
函数,可轻松对列进行重新排序:

data.table::setcolorder(table, c("Out", "in", "files"))
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)


help(Extract)
也称为
?'['
除了@Joris的建议外,请尝试阅读“R简介”的第2.7节和第5节手册:另一个问题:所有答案都需要完整的列列表,否则会导致子集。如果我们只想列出一些列作为第一列进行排序,但同时保留所有其他列,那会怎么样?如果列的数量有限,这是可以的,但是如果您有50列,那就太多了输入所有列号或名称的时间到了。什么是更快的解决方案?@user4050:在这种情况下,您可以使用“:”语法,例如df[,c(1,3,2,4,5:50)]。要将列放在idcols开头:idcols@user4050:当您不知道有多少列时,也可以使用
df[,c(1,3,2,4:ncol(df))
。您还可以使用dput(colnames)(df)),它以R字符格式打印列名。然后可以重新排列列名。不使用
subset()有一些原因
,请参阅。谢谢。在任何情况下,我现在都会使用dplyr包中的select函数,而不是子集。当您想将两列放到左侧,而不丢弃其他列时,我发现
everything()
特别棒;
mtcars%>%select(wt、gear、everything())
这里是另一种使用everything()select\u helper函数将列重新排列到右边/尽头的方法。似乎您需要使用2个select()新函数dplyr::relocate正是为了实现这一点。请看下面的H1的答案。作为初学者,您能否将按索引和按名称排序结合起来?例如,
data@BramVanroy nope,
c(1,3,“Var1”,2)
将被理解为
c(“1”,“3”,“Var1”,“2”)
因为向量只能包含一种类型的数据,所以类型被提升为当前最通用的类型。因为没有字符名为“1”、“3”等的列。您将得到“未定义的列”。
列表(1,3,“Var1”,2)
在不进行类型升级的情况下保留值,但在上述上下文中不能使用
列表。为什么
mtcars[c(1,3,2)]
子集设置有效?我会预料到与不正确的尺寸或类似尺寸相关的错误…它不应该是
mtcars[,c(1,3,2)]
?data.frames是隐藏在引擎盖下的列表,列是一阶项非常好的功能。我在我的中添加了此功能的修改版本。这非常有用-当我只想将一列从一个非常宽的TIBLE的末尾移到开头时,这将节省我很多时间。这是我的最佳选择。即使我必须安装它,这显然是最明显的可能性。Tidyverse(事实上是dplyr)还可以选择列组,例如将物种变量移到前面:
select(iris,Species,everything())
。还请注意,不需要引号。重要的是,这将删除所有未明确指定的列,除非包含
所有内容()
正如PaulRougieux的评论
dplyr
组也将重新排列变量,因此在链中使用时要小心。从
dplyr
版本
1.0.0
开始,他们添加了一个
重定位()
函数,直观且易于阅读。如果您只想在特定列之后或之前添加列,则此函数特别有用。
!!警告!!
数据。表将
目标
转换为int向量:
目标请说明使用f的库
arrange.vars(table, c("Out"=2, "Files"=1, "Time"=4))
##  Files Out In Time
##1     4   3  2    1
##2     5   4  3    2
 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")]
select(table, "Time", "Out", "In", "Files") 

# or

select(table, Time, Out, In, Files)
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")]
data <- data %>% select(Time, out, In, Files)
data.table::setcolorder(table, c("Out", "in", "files"))
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)