데이터 프레임에서 열을 어떻게 재정렬합니까?


311

시간, 입력, 출력, 파일 순서대로이 입력을 어떻게 변경합니까?

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

4
help(Extract)라고도?'['
Joris Meys

3
@Joris의 제안 외에도 "R 소개"매뉴얼의 섹션 2.7과 섹션 5를 읽으십시오
Gavin Simpson

3
한 가지 추가 문제 : 모든 답변에는 전체 열 목록이 필요합니다. 그렇지 않으면 하위 집합이 발생합니다. 첫 번째 열로 주문할 열을 몇 개만 나열하고 나머지 열도 모두 유지하려면 어떻게해야합니까?
000andy8484

답변:


341

데이터 프레임에는 이와 같은 네 개의 열이 df[,c(1,2,3,4)]있습니다. 첫 번째 쉼표는 모든 행을 유지하고 1,2,3,4는 열을 나타냅니다.

위의 질문에서와 같이 순서를 변경하려면 df2[,c(1,3,2,4)]

이 파일을 csv로 출력하려면 write.csv(df2, file="somedf.csv")


35
열 수가 제한되어 있으면 괜찮지 만, 예를 들어 열이 50 개인 경우 모든 열 번호 나 이름을 입력하는 데 시간이 너무 오래 걸립니다. 더 빠른 해결책은 무엇입니까?
Herman Toothrot

54
@ user4050 :이 경우 ":"구문을 사용할 수 있습니다 (예 : df [, c (1,3,2,4,5 : 50)]).
dalloliogm

1
시작시 idcols에 열을 넣으려면 : idcols <-c ( "name", "id2", "start", "duration"); cols <-c (idcols, names (cts) [-which (names (cts) % in % idcols)]); df <
-df

13
@ user4050 : df[,c(1,3,2,4:ncol(df))]얼마나 많은 열이 있는지 모르는 경우 에도 사용할 수 있습니다 .
arekolek

1
dput (colnames (df))을 사용할 수도 있으며 열 이름을 R 문자 형식으로 인쇄합니다. 그런 다음 이름을 다시 정렬 할 수 있습니다.
Chris

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

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

1
초보자로서 질문, 당신은 색인과 이름으로 순서를 결합 할 수 있습니까? 예를 들어 data <- data[c(1,3,"Var1", 2)]?
Bram Vanroy

6
@BramVanroy nope c(1,3,"Var1", 2)c("1","3","Var1", "2")벡터가 한 유형의 데이터 만 포함 할 수 있으므로 가장 일반적인 유형으로 승격됩니다. 문자 이름이 "1", "3"등인 열이 없으므로 "정의되지 않은 열"이 표시됩니다. list(1,3,"Var1", 2)유형 승격없이 값을 유지하지만 list위의 컨텍스트에서를 사용할 수 없습니다 .
Terry Brown

1
mtcars[c(1,3,2)]서브셋이 작동 하는 이유는 무엇 입니까? 잘못된 치수 또는 이와 유사한 오류가 발생했을 것으로 예상됩니다. 그렇지 mtcars[,c(1,3,2)]않습니까?
landroni

data.frames는 일차 항목으로 열이 후드리스트이다
petermeissner

106

서브셋 기능을 사용할 수도 있습니다.

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의 select 구문 에 대해 자세히 알아보십시오 .


5
사용하지 않는 몇 가지 이유가 있습니다 . 이 질문을subset() 참조하십시오 .
MERose

2
감사합니다. 어쨌든 이제는 하위 집합 대신 dplyr 패키지의 select 함수를 사용합니다.
dalloliogm

87
왼쪽에 몇 개의 열을 가져오고 다른 열을 떨어 뜨리지 않으려는 경우 everything()특히 굉장합니다. mtcars %>% select(wt, gear, everything())
guyabel

2
다음은 everything () select_helper 함수를 사용하여 열을 오른쪽 / 끝으로 다시 정렬하는 다른 방법입니다. stackoverflow.com/a/44353144/4663008 github.com/tidyverse/dplyr/issues/2838 일부 열을 오른쪽 끝으로 이동하고 다른 열을 왼쪽으로 이동하려면 2 select ()를 사용해야하는 것처럼 보입니다.
Arthur Yip

1
새로운 기능 dplyr :: relocate가 바로 이것입니다. 아래 H 1의 답변 참조
Arthur Yip

39

이 의견 에서 언급했듯이 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

아주 좋은 기능. 개인 패키지 에이 기능의 수정 된 버전을 추가했습니다 .
Deleet

1
이건 정말 유용합니다 - 난 그냥 처음에 정말 넓은 tibble의 끝에서 하나의 열을 이동하고자 할 때 나에게 많은 시간을 절약 할 것
Mrmoleje

와우, 나는 이것을 좋아한다.
OfTheAzureSky

37

dplyr용액 (일부의 tidyverse패키지 집합)를 사용하는 것이다 select:

select(table, "Time", "Out", "In", "Files") 

# or

select(table, Time, Out, In, Files)

2
나에게 가장 좋은 옵션. 설치해야하더라도 분명히 가장 분명한 가능성입니다.
가리 니

15
Tidyverse (사실 dplyr)에는 예를 들어 Species 변수를 앞으로 이동하는 것과 같이 열 그룹을 선택하는 옵션이 select(iris, Species, everything())있습니다. 또한 따옴표는 필요하지 않습니다.
Paul Rougieux

3
everything()PaulRougieux의 의견에 포함되지 않은 한 명시 적으로 지정되지 않은 모든 열이 삭제됩니다 .
divibisan

dplyr집은 group또한 체인 것을 사용하면 매우 조심 변수를 재 배열한다.
David Tonhofer

26

원하는 열 순서가 알파벳 순서로 내림차순으로 표시되는 것은 우연의 일치 일 수 있습니다. 그것이 바로 당신이 할 수있는 경우이기 때문에 :

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

열이 많은 큰 파일이있을 때 사용합니다.


!! WARNING !! data.table회전 TARGET하는 int 벡터로는 : TARGET <- TARGET[ , order(colnames(TARGET), decreasing=TRUE)] 해결하기 위해 그 : TARGET <- as.data.frame(TARGET) TARGET <- TARGET[ , order(colnames(TARGET), decreasing=TRUE)]
재커리 라이언 스미스


12

세 개의 최고 등급 대답은 약점이있다.

데이터 프레임이 다음과 같은 경우

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을 사용하면select

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

그런 다음 나중에 자신을 포함하여 코드를 읽는 사람을 속여서 속일 수 있습니다. 열 이름은 코드에 그대로 표시되지 않고 리터럴로 사용됩니다.


3

dplyrversion 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)


1

내가 잘 작동 한 유일한 것은 여기 입니다.

 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")]

매력처럼 작동합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.