是否有一种方法可以将列从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+列)
答案 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 = TRUE
在move_this
之前移动next_to_this
。
<强>示例:强>
move.col(df, "b", "g")
move.col(df, "c", "e")
move.col(df, "g", "a", before=TRUE)
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)
这是一个可能有用的功能
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])]