여러 열로 데이터 프레임을 정렬하는 방법


1316

data.frame을 여러 열로 정렬하고 싶습니다. 예를 들어 아래의 data.frame을 사용하면 zb(오름차순) , 열 (오름차순) 별로 정렬하고 싶습니다 .

dd <- data.frame(b = factor(c("Hi", "Med", "Hi", "Low"), 
      levels = c("Low", "Med", "Hi"), ordered = TRUE),
      x = c("A", "D", "A", "C"), y = c(8, 3, 9, 9),
      z = c(1, 1, 1, 2))
dd
    b x y z
1  Hi A 8 1
2 Med D 3 1
3  Hi A 9 1
4 Low C 9 2

답변:


1625

order()애드온 툴에 의존하지 않고 함수를 직접 사용할 수 있습니다 . example(order)코드 상단에서 트릭을 사용하는 간단한 답변을 참조하십시오 .

R> dd[with(dd, order(-z, b)), ]
    b x y z
4 Low C 9 2
2 Med D 3 1
1  Hi A 8 1
3  Hi A 9 1

약 2 년 후에 편집 : 방금 인덱스로이를 수행하는 방법을 묻습니다. 답은 단순히 원하는 정렬 열을 order()함수에 전달하는 것입니다.

R> dd[order(-dd[,4], dd[,1]), ]
    b x y z
4 Low C 9 2
2 Med D 3 1
1  Hi A 8 1
3  Hi A 9 1
R> 

열 이름을 사용하는 대신 (보다 with()쉽고 직접적인 액세스).


@ Dirk Eddelbuettel 행렬에 대해서도 비슷한 간단한 방법이 있습니까?
Jota

14
같은 방식으로 작동하지만을 사용할 수 없습니다 with. 시도 M <- matrix(c(1,2,2,2,3,6,4,5), 4, 2, byrow=FALSE, dimnames=list(NULL, c("a","b")))행렬을 생성 M한 후, 사용 M[order(M[,"a"],-M[,"b"]),]이 열을 주문할 수 있습니다.
Dirk Eddelbuettel

4
충분히 간단 dd[ order(-dd[,4], dd[,1]), ]하지만 with이름 기반 하위 설정 에는 사용할 수 없습니다 .
Dirk Eddelbuettel

18
두 번째 예를 실행하는 동안 "단항 연산자에 대한 잘못된 인수"오류가 발생했습니다.
Nailgun

21
문자 열과 함께 빼기를 사용하면 "단항 연산자에 대한 잘못된 인수"오류가 발생합니다. xtfrm예를 들어 열을 감싸서 해결하십시오 dd[ order(-xtfrm(dd[,4]), dd[,1]), ].
Richie Cotton

477

당신의 선택

  • order ...에서 base
  • arrange ...에서 dplyr
  • setordersetorderv에서data.table
  • arrange ...에서 plyr
  • sort ...에서 taRifx
  • orderBy ...에서 doBy
  • sortData ...에서 Deducer

의존성이없는 것이 중요하지 않은 한 대부분의 경우 dplyr또는 data.table솔루션을 사용해야 base::order합니다.


최근에 sort.data.frame을 CRAN 패키지에 추가하여 다음과 같이 클래스를 호환 가능하게 만들었습니다. sort.data.frame의 일반 / 방법 일관성을 만드는 가장 좋은 방법은 무엇입니까?

따라서 data.frame dd가 주어지면 다음과 같이 정렬 할 수 있습니다.

dd <- data.frame(b = factor(c("Hi", "Med", "Hi", "Low"), 
      levels = c("Low", "Med", "Hi"), ordered = TRUE),
      x = c("A", "D", "A", "C"), y = c(8, 3, 9, 9),
      z = c(1, 1, 1, 2))
library(taRifx)
sort(dd, f= ~ -z + b )

이 기능의 원저자 중 하나 인 경우 저에게 연락하십시오. 공개 도메인에 대한 토론은 여기에 있습니다 : http://chat.stackoverflow.com/transcript/message/1094290#1094290


Hadley가 위의 스레드에서 지적한 것처럼 arrange()함수를 사용할 수도 있습니다 plyr.

library(plyr)
arrange(dd,desc(z),b)

벤치 마크 : 많은 충돌이 있었으므로 새 R 세션에서 각 패키지를로드했습니다. 특히 doBy 패키지를로드하면 sort"다음 객체가 'x (위치 17)'에서 마스크됩니다 : b, x, y, z"가 반환되고 Deducer 패키지를로드하면 sort.data.frameKevin Wright 또는 taRifx 패키지에서 덮어 씁니다 .

#Load each time
dd <- data.frame(b = factor(c("Hi", "Med", "Hi", "Low"), 
      levels = c("Low", "Med", "Hi"), ordered = TRUE),
      x = c("A", "D", "A", "C"), y = c(8, 3, 9, 9),
      z = c(1, 1, 1, 2))
library(microbenchmark)

# Reload R between benchmarks
microbenchmark(dd[with(dd, order(-z, b)), ] ,
    dd[order(-dd$z, dd$b),],
    times=1000
)

평균 시간 :

dd[with(dd, order(-z, b)), ] 778

dd[order(-dd$z, dd$b),] 788

library(taRifx)
microbenchmark(sort(dd, f= ~-z+b ),times=1000)

평균 시간 : 1,567

library(plyr)
microbenchmark(arrange(dd,desc(z),b),times=1000)

평균 시간 : 862

library(doBy)
microbenchmark(orderBy(~-z+b, data=dd),times=1000)

평균 시간 : 1,694

doBy는 패키지를로드하는 데 약간의 시간이 걸립니다.

library(Deducer)
microbenchmark(sortData(dd,c("z","b"),increasing= c(FALSE,TRUE)),times=1000)

Deducer를로드하지 못했습니다. JGR 콘솔이 필요합니다.

esort <- function(x, sortvar, ...) {
attach(x)
x <- x[with(x,order(sortvar,...)),]
return(x)
detach(x)
}

microbenchmark(esort(dd, -z, b),times=1000)

부착 / 분리로 인해 마이크로 벤치 마크와 호환되지 않는 것 같습니다.


m <- microbenchmark(
  arrange(dd,desc(z),b),
  sort(dd, f= ~-z+b ),
  dd[with(dd, order(-z, b)), ] ,
  dd[order(-dd$z, dd$b),],
  times=1000
  )

uq <- function(x) { fivenum(x)[4]}  
lq <- function(x) { fivenum(x)[2]}

y_min <- 0 # min(by(m$time,m$expr,lq))
y_max <- max(by(m$time,m$expr,uq)) * 1.05

p <- ggplot(m,aes(x=expr,y=time)) + coord_cartesian(ylim = c( y_min , y_max )) 
p + stat_summary(fun.y=median,fun.ymin = lq, fun.ymax = uq, aes(fill=expr))

마이크로 벤치 마크 플롯

(선은 사분 위에서 사분 위로 이어지고 점은 중앙값입니다)


이러한 결과를 감안할 때 단순 비교 속도를 무게, 나는에 고개를 끄덕 제공해야 할 것 arrangeplyr패키지 . 간단한 구문을 가지고 있지만 복잡한 기계 가공을 사용하는 기본 R 명령만큼이나 빠릅니다. 일반적으로 훌륭한 Hadley Wickham이 작업합니다. 그것에 대한 유일한 견해는 정렬 객체가 호출되는 표준 R 명명법을 위반한다는 것입니다 sort(object).하지만 위의 질문에서 논의 된 문제로 인해 Hadley가 왜 그렇게했는지 이해합니다.


3
위의 ggplot2 microbenchmark 기능은 이제로 사용할 수 있습니다 taRifx::autoplot.microbenchmark.
Ari B. Friedman 2012 년

@ AriB.Friedman y 축 간격은 얼마입니까 / 눈금은 얼마입니까?
naught101

@ naught101 y 축은 0에서 시작합니다. 스케일은 마이크로 초 여야합니다.
Ari B. Friedman

2
@AME b는 샘플 에서 어떻게 정렬 되는지 봅니다 . 기본값은 오름차순으로 정렬되므로로 묶지 마십시오 desc. 둘 다 오름차순 : arrange(dd,z,b). 둘 다 내림차순 : arrange(dd,desc(z),desc(b)).
Ari B. Friedman

2
?arrange: "# 참고 : plyr 기능 row.names을 유지하지 않습니다." 이것은 arrange()유지하려는 경우 우수한 기능을 차선책으로 만듭니다 row.names.
landroni

148

더크의 대답은 훌륭합니다. 또한 data.frames 및 data.tables 를 인덱싱하는 데 사용되는 구문의 주요 차이점을 강조합니다 .

## The data.frame way
dd[with(dd, order(-z, b)), ]

## The data.table way: (7 fewer characters, but that's not the important bit)
dd[order(-z, b)]

두 통화의 차이는 작지만 중요한 결과를 초래할 수 있습니다. 특히 생산 코드를 작성하거나 연구의 정확성에 관심이있는 경우 변수 이름의 불필요한 반복을 피하는 것이 가장 좋습니다. data.table 이렇게 도와줍니다.

다음은 변수 이름의 반복으로 인해 문제가 발생할 수있는 예입니다.

Dirk의 답변에서 컨텍스트를 변경하고 이것이 많은 객체 이름이 있고 길고 의미있는 더 큰 프로젝트의 일부라고 가정 해 봅시다. 대신 dd이라고 quarterlyreport합니다. 그것은된다 :

quarterlyreport[with(quarterlyreport,order(-z,b)),]

알았어 괜찮아. 아무 문제가 없습니다. 다음으로 상사는 보고서에 지난 분기의 보고서를 포함하도록 요청합니다. 코드를 통해 lastquarterlyreport다양한 장소에 객체 를 추가 하고 어떻게 든 지구상에서 어떻게해야합니까?

quarterlyreport[with(lastquarterlyreport,order(-z,b)),]

그것은 당신이 의미하는 것이 아니지만 당신이 그것을 빨리하고 비슷한 코드의 페이지에 중첩되어 있기 때문에 그것을 발견하지 못했습니다. R은 그것이 당신이 의도 한 것이라고 생각하기 때문에 코드가 넘어지지 않습니다 (경고 및 오류 없음). 보고서를 읽는 사람이 그것을 발견하길 바라지 만 그렇지 않을 수도 있습니다. 프로그래밍 언어를 많이 사용한다면이 상황은 모두에게 익숙 할 것입니다. 당신이 말할 "오타"였습니다. 상사에게 말할 "오타"를 고칠 게요.

data.table우리는 이와 같은 작은 세부 사항에 대해 걱정하고 있습니다. 따라서 변수 이름을 두 번 입력하지 않도록 간단한 작업을 수행했습니다. 매우 간단한 것. 이미 자동으로 i프레임 내에서 평가 dd됩니다. 당신은 전혀 필요하지 않습니다 with().

대신에

dd[with(dd, order(-z, b)), ]

그냥

dd[order(-z, b)]

그리고 대신

quarterlyreport[with(lastquarterlyreport,order(-z,b)),]

그냥

quarterlyreport[order(-z,b)]

그것은 아주 작은 차이이지만, 하루 만에 목을 구할 수도 있습니다. 이 질문에 대한 다른 답변을 계량 할 때 결정의 기준 중 하나로 변수 이름의 반복을 계산하는 것을 고려하십시오. 일부 답변은 반복이 많고 다른 답변은 없습니다.


9
+1 이것은 좋은 점이며, 종종 저를 화나게 한 R의 구문에 대해 자세히 알아 봅니다. 때로는 subset()단일 호출 내에서 동일한 객체를 반복적으로 참조하지 않아도됩니다.
Josh O'Brien

2
@ naught101 data.table FAQ 1.9가 대답합니까?
매트 Dowle

5
setorder이 스레드가 모든 order유형의 속임수를 보내는 위치이므로 여기에 새로운 기능을 추가 할 수 있다고 생각합니다 .
David Arenburg

125

여기에는 훌륭한 답변이 많이 있지만 dplyr 은 빠르고 쉽게 기억할 수있는 유일한 구문을 제공합니다 (따라서 매우 자주 사용).

library(dplyr)
# sort mtcars by mpg, ascending... use desc(mpg) for descending
arrange(mtcars, mpg)
# sort mtcars first by mpg, then by cyl, then by wt)
arrange(mtcars , mpg, cyl, wt)

OP의 문제 :

arrange(dd, desc(z),  b)

    b x y z
1 Low C 9 2
2 Med D 3 1
3  Hi A 8 1
4  Hi A 9 1

2
열이 열이거나 유형 요소 (또는 이와 유사한 것) 일 때 허용되는 대답이 작동하지 않으며이 요소 열에 대해 내림차순으로 정렬하고 정수 열을 오름차순으로 정렬하려고합니다. 그러나 이것은 잘 작동합니다! 감사합니다!
Saheel Godhane

10
왜 "만"? data.table은 dd[order(-z, b)]사용하기 쉽고 기억하기 쉽습니다.
Matt Dowle

2
동의, 그 두 방법 사이에는 많지 않으며 다른 많은 방법에도 data.table큰 기여를 R합니다. 나는이 경우에 하나의 적은 괄호 세트 (또는 하나의 더 적은 유형의 괄호)를 가짐으로써인지 부하를 거의 인식 할 수없는 양만큼 줄인다고 생각합니다.
Ben

7
나를 위해 그것은 arrange()완전히 선언적 이라는 사실에 달려 dd[order(-z, b)]있습니다.
Mullefa

83

R 패키지 data.table는 간단한 구문으로 Matt. 빠른 속도메모리 효율적인 data.tables 순서를 제공 합니다 (Mat가 그의 대답에서 아주 잘 강조 표시 했습니다 ). 그 이후로 많은 개선과 새로운 기능이 setorder()있었습니다. 에서 v1.9.5+, setorder()또한 작동 data.frames .

먼저 충분히 큰 데이터 세트를 만들고 다른 답변에서 언급 한 다양한 방법을 벤치마킹 한 다음 data.table 의 기능을 나열 합니다.

데이터:

require(plyr)
require(doBy)
require(data.table)
require(dplyr)
require(taRifx)

set.seed(45L)
dat = data.frame(b = as.factor(sample(c("Hi", "Med", "Low"), 1e8, TRUE)),
                 x = sample(c("A", "D", "C"), 1e8, TRUE),
                 y = sample(100, 1e8, TRUE),
                 z = sample(5, 1e8, TRUE), 
                 stringsAsFactors = FALSE)

벤치 마크 :

보고 된 타이밍은 system.time(...)아래에 표시된 이러한 기능 에서 실행 된 것입니다. 타이밍은 가장 느리거나 빠른 순서로 아래에 표로 표시되어 있습니다.

orderBy( ~ -z + b, data = dat)     ## doBy
plyr::arrange(dat, desc(z), b)     ## plyr
arrange(dat, desc(z), b)           ## dplyr
sort(dat, f = ~ -z + b)            ## taRifx
dat[with(dat, order(-z, b)), ]     ## base R

# convert to data.table, by reference
setDT(dat)

dat[order(-z, b)]                  ## data.table, base R like syntax
setorder(dat, -z, b)               ## data.table, using setorder()
                                   ## setorder() now also works with data.frames 

# R-session memory usage (BEFORE) = ~2GB (size of 'dat')
# ------------------------------------------------------------
# Package      function    Time (s)  Peak memory   Memory used
# ------------------------------------------------------------
# doBy          orderBy      409.7        6.7 GB        4.7 GB
# taRifx           sort      400.8        6.7 GB        4.7 GB
# plyr          arrange      318.8        5.6 GB        3.6 GB 
# base R          order      299.0        5.6 GB        3.6 GB
# dplyr         arrange       62.7        4.2 GB        2.2 GB
# ------------------------------------------------------------
# data.table      order        6.2        4.2 GB        2.2 GB
# data.table   setorder        4.5        2.4 GB        0.4 GB
# ------------------------------------------------------------
  • data.tableDT[order(...)]구문은 다른 방법 중 가장 빠른 방법 ( ~) 보다 ~ 10 배 빠르지 만와dplyr 같은 양의 메모리를 소비합니다 dplyr.

  • data.table'들 setorder()이었다 ~ 14 배 빠른 다른 방법 (가장 빠른보다는 dplyr하면서,) 단지 0.4GB 추가 메모리를 . dat이제 우리가 요구하는 순서대로되어 있습니다 (참조에 의해 업데이트 됨).

data.table 기능 :

속도:

  • data.table 의 순서는 기수 순서를 구현하기 때문에 매우 빠릅니다 .

  • 구문 DT[order(...)]data.table 의 빠른 순서도 사용하도록 내부적으로 최적화 됩니다. 친숙한 기본 R 구문을 계속 사용하면서 프로세스 속도를 높이고 메모리를 적게 사용할 수 있습니다.

기억:

  • 시간의 대부분은, 우리는 원래 필요하지 않습니다 data.frame 또는 data.table 재정렬 후를. 즉, 일반적으로 결과를 동일한 객체에 다시 할당합니다. 예를 들면 다음과 같습니다.

    DF <- DF[order(...)]

    문제는 원본 객체의 메모리에 최소 두 배 (2x)의 메모리가 필요하다는 것입니다. 로 메모리 효율 , data.table 때문에 또한 기능을 제공합니다 setorder().

    setorder()추가 사본을 만들지 않고 data.tables by reference ( in-place )를 재정렬 합니다. 하나의 열 크기와 동일한 추가 메모리 만 사용합니다.

다른 특징들:

  1. 그것은 지원 integer, logical, numeric, character심지어 bit64::integer64유형.

    하는 것으로 factor, Date, POSIXct등의 클래스는 모두 integer/ numeric유형 추가 속성을 아래에 따라서도 지원됩니다.

  2. 기수 R에서는 -문자형 벡터를 사용 하여 해당 열을 기준으로 내림차순으로 정렬 할 수 없습니다 . 대신 우리는를 사용해야 -xtfrm(.)합니다.

    그러나에 data.table , 우리는 단지 예를 들어, 수행 할 수 있습니다 dat[order(-x)]또는 setorder(dat, -x).


data.table에 대한 매우 유익한 답변에 감사드립니다. 그러나 "피크 메모리"란 무엇이며 어떻게 계산했는지 이해하지 못합니다. 설명해 주시겠습니까? 감사합니다 !
Julien Navarre 2016 년

기기 -> 할당을 사용 하고 "모든 힙 및 할당 VM"크기를보고했습니다.
Arun

2
댓글에서 인스트루먼트 링크를 실행하십시오. 업데이트를 게시 하시겠습니까?
MichaelChirico

@MichaelChirico 다음은 Apple에서 만든 인스트루먼트에 대한 정보 링크입니다. developer.apple.com/library/content/documentation/…
n1k31t4


39

또는 doBy 패키지를 사용할 수 있습니다

library(doBy)
dd <- orderBy(~-z+b, data=dd)

39

a가 data.frame A있고 x내림차순 이라는 열을 사용하여 정렬 한다고 가정하십시오 . 정렬 된 전화data.frame newdata

newdata <- A[order(-A$x),]

오름차순으로 주문하려면 "-"아무것도 바꾸지 마십시오. 당신은 같은 것을 가질 수 있습니다

newdata <- A[order(-A$x, A$y, -A$z),]

어디에 xz일부 열이 data.frame A있습니다. 이것은 내림차순, 오름차순 및 내림차순 으로 정렬 data.frame A하는 것을 의미 합니다.xyz


32

SQL이 자연스럽게 제공되면 sqldf패키지는 ORDER BYCodd가 의도 한대로 처리합니다 .


7
MJM,이 패키지를 지적 해 주셔서 감사합니다. 그것은 매우 유연하고 내 작업의 절반이 이미 SQL 데이터베이스에서 가져 와서 수행되기 때문에 직관적 인 구문보다 R의 많은 부분을 배우는 것보다 쉽습니다.
Brandon Bertelsen

31

또는 Deducer 패키지 사용

library(Deducer)
dd<- sortData(dd,c("z","b"),increasing= c(FALSE,TRUE))

19

프로그래밍 방식으로 정렬하는 방법에 대해 OP에 추가 된 의견에 대한 답변 :

사용 dplyr하여data.table

library(dplyr)
library(data.table)

dplyr

arrange_대한 표준 평가 버전 인을 사용하십시오 arrange.

df1 <- tbl_df(iris)
#using strings or formula
arrange_(df1, c('Petal.Length', 'Petal.Width'))
arrange_(df1, ~Petal.Length, ~Petal.Width)
    Source: local data frame [150 x 5]

   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
          (dbl)       (dbl)        (dbl)       (dbl)  (fctr)
1           4.6         3.6          1.0         0.2  setosa
2           4.3         3.0          1.1         0.1  setosa
3           5.8         4.0          1.2         0.2  setosa
4           5.0         3.2          1.2         0.2  setosa
5           4.7         3.2          1.3         0.2  setosa
6           5.4         3.9          1.3         0.4  setosa
7           5.5         3.5          1.3         0.2  setosa
8           4.4         3.0          1.3         0.2  setosa
9           5.0         3.5          1.3         0.3  setosa
10          4.5         2.3          1.3         0.3  setosa
..          ...         ...          ...         ...     ...


#Or using a variable
sortBy <- c('Petal.Length', 'Petal.Width')
arrange_(df1, .dots = sortBy)
    Source: local data frame [150 x 5]

   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
          (dbl)       (dbl)        (dbl)       (dbl)  (fctr)
1           4.6         3.6          1.0         0.2  setosa
2           4.3         3.0          1.1         0.1  setosa
3           5.8         4.0          1.2         0.2  setosa
4           5.0         3.2          1.2         0.2  setosa
5           4.7         3.2          1.3         0.2  setosa
6           5.5         3.5          1.3         0.2  setosa
7           4.4         3.0          1.3         0.2  setosa
8           4.4         3.2          1.3         0.2  setosa
9           5.0         3.5          1.3         0.3  setosa
10          4.5         2.3          1.3         0.3  setosa
..          ...         ...          ...         ...     ...

#Doing the same operation except sorting Petal.Length in descending order
sortByDesc <- c('desc(Petal.Length)', 'Petal.Width')
arrange_(df1, .dots = sortByDesc)

자세한 정보는 여기 : https://cran.r-project.org/web/packages/dplyr/vignettes/nse.html

식을 평가하기 위해 환경을 캡처하기 때문에 수식을 사용하는 것이 좋습니다.

data.table

dt1 <- data.table(iris) #not really required, as you can work directly on your data.frame
sortBy <- c('Petal.Length', 'Petal.Width')
sortType <- c(-1, 1)
setorderv(dt1, sortBy, sortType)
dt1
     Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
  1:          7.7         2.6          6.9         2.3 virginica
  2:          7.7         2.8          6.7         2.0 virginica
  3:          7.7         3.8          6.7         2.2 virginica
  4:          7.6         3.0          6.6         2.1 virginica
  5:          7.9         3.8          6.4         2.0 virginica
 ---                                                            
146:          5.4         3.9          1.3         0.4    setosa
147:          5.8         4.0          1.2         0.2    setosa
148:          5.0         3.2          1.2         0.2    setosa
149:          4.3         3.0          1.1         0.1    setosa
150:          4.6         3.6          1.0         0.2    setosa

18

나는 order다음 예제를 통해 배우고 오랫동안 나를 혼란스럽게했다.

set.seed(1234)

ID        = 1:10
Age       = round(rnorm(10, 50, 1))
diag      = c("Depression", "Bipolar")
Diagnosis = sample(diag, 10, replace=TRUE)

data = data.frame(ID, Age, Diagnosis)

databyAge = data[order(Age),]
databyAge

이 예제가 작동하는 유일한 이유는 에서 이름이 지정된 열 이 아니라을 기준 order으로 정렬 하기 때문 입니다 .vector AgeAgedata frame data

이를 확인하려면 read.table약간 다른 열 이름을 사용하고 위의 벡터를 사용하지 않고 동일한 데이터 프레임을 만듭니다 .

my.data <- read.table(text = '

  id age  diagnosis
   1  49 Depression
   2  50 Depression
   3  51 Depression
   4  48 Depression
   5  50 Depression
   6  51    Bipolar
   7  49    Bipolar
   8  49    Bipolar
   9  49    Bipolar
  10  49 Depression

', header = TRUE)

order이름이 지정된 벡터가 없으므로 위의 라인 구조는 더 이상 작동하지 않습니다 age.

databyage = my.data[order(age),]

다음 줄은 때문에 작동 order열에 종류 age에서 my.data.

databyage = my.data[order(my.data$age),]

나는이 예제에 의해 얼마나 오랫동안 혼란스러워했는지 게시 할 가치가 있다고 생각했습니다. 이 게시물이 스레드에 적합하지 않은 것으로 판단되면 제거 할 수 있습니다.

편집 : 2014 년 5 월 13 일

다음은 열 이름을 지정하지 않고 모든 열을 기준으로 데이터 프레임을 정렬하는 일반적인 방법입니다. 아래 코드는 왼쪽에서 오른쪽으로 또는 오른쪽에서 왼쪽으로 정렬하는 방법을 보여줍니다. 모든 열이 숫자 인 경우 작동합니다. 문자 열을 추가하여 시도하지 않았습니다.

do.call한 달 또는 두 달 전에 다른 사이트의 오래된 게시물에서 코드를 찾았 지만 광범위하고 어려운 검색 후에 만 ​​가능했습니다. 해당 게시물을 지금 재배치 할 수 있는지 잘 모르겠습니다. 현재 스레드는 data.framein 을 주문하기위한 첫 번째 적중입니다 R. 그래서 원래 do.call코드 의 확장 버전 이 유용 할 것이라고 생각했습니다 .

set.seed(1234)

v1  <- c(0,0,0,0, 0,0,0,0, 1,1,1,1, 1,1,1,1)
v2  <- c(0,0,0,0, 1,1,1,1, 0,0,0,0, 1,1,1,1)
v3  <- c(0,0,1,1, 0,0,1,1, 0,0,1,1, 0,0,1,1)
v4  <- c(0,1,0,1, 0,1,0,1, 0,1,0,1, 0,1,0,1)

df.1 <- data.frame(v1, v2, v3, v4) 
df.1

rdf.1 <- df.1[sample(nrow(df.1), nrow(df.1), replace = FALSE),]
rdf.1

order.rdf.1 <- rdf.1[do.call(order, as.list(rdf.1)),]
order.rdf.1

order.rdf.2 <- rdf.1[do.call(order, rev(as.list(rdf.1))),]
order.rdf.2

rdf.3 <- data.frame(rdf.1$v2, rdf.1$v4, rdf.1$v3, rdf.1$v1) 
rdf.3

order.rdf.3 <- rdf.1[do.call(order, as.list(rdf.3)),]
order.rdf.3

4
data.frame 대신 data.table에 데이터를 저장하면이 구문 require(data.table); my.dt <- data.table(my.data); my.dt[order(age)]이 작동합니다. 열 이름을 [] 괄호 안에 사용할 수 있기 때문에 작동합니다.
Frank

나는 downvote 여기에 필요하다고 생각하지 않는다, 그러나 어느 쪽도 아니 나는 이것이에 많은 추가 생각하십니까 질문 특히 이미와 요구 사항 캡처 일부 답변, 기존의 설정을 고려, 손 data.frame중 하나를 사용들 with또는 $.
A5C1D2H2I1M1N2O1R2T1 1

1
이를위한 공감대 do.call는 다중 열 데이터 프레임을 정렬하는 짧은 작업을 만듭니다. 간단 do.call(sort, mydf.obj)하고 아름다운 캐스케이드 종류가 있습니다.
AdamO

17

Dirk의 대답은 좋지만 정렬을 유지하려면 정렬을 해당 데이터 프레임의 이름에 다시 적용하고 싶을 것입니다. 예제 코드 사용 :

dd <- dd[with(dd, order(-z, b)), ] 

13

dplyer의 adjust ()는 내가 가장 좋아하는 옵션입니다. 파이프 연산자를 사용하여 가장 중요하지 않은 측면에서 가장 중요한 측면으로 이동

dd1 <- dd %>%
    arrange(z) %>%
    arrange(desc(x))

7

완전성을 위해 열 번호별로 정렬하는 것에 대해 많이 언급되지 않았기 때문에 ... 열의 순서가 변경되어 오류가 발생할 수 있기 때문에 바람직하지 않다고 주장 할 수 있지만 특정 상황에서 (예를 들어 빠른 작업이 필요하고 열이 순서를 변경하는 위험이없는 경우), 특히 많은 수의 열을 처리 할 때 가장 합리적인 방법 일 수 있습니다.

이 경우 do.call()구조에 온다 :

ind <- do.call(what = "order", args = iris[,c(5,1,2,3)])
iris[ind, ]

##        Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
##    14           4.3         3.0          1.1         0.1     setosa
##    9            4.4         2.9          1.4         0.2     setosa
##    39           4.4         3.0          1.3         0.2     setosa
##    43           4.4         3.2          1.3         0.2     setosa
##    42           4.5         2.3          1.3         0.3     setosa
##    4            4.6         3.1          1.5         0.2     setosa
##    48           4.6         3.2          1.4         0.2     setosa
##    7            4.6         3.4          1.4         0.3     setosa
##    (...)

6

완벽을 기하기 위해 패키지에서이 sortByCol()기능을 사용할 수도 있습니다 BBmisc.

library(BBmisc)
sortByCol(dd, c("z", "b"), asc = c(FALSE, TRUE))
    b x y z
4 Low C 9 2
2 Med D 3 1
1  Hi A 8 1
3  Hi A 9 1

성능 비교 :

library(microbenchmark)
microbenchmark(sortByCol(dd, c("z", "b"), asc = c(FALSE, TRUE)), times = 100000)
median 202.878

library(plyr)
microbenchmark(arrange(dd,desc(z),b),times=100000)
median 148.758

microbenchmark(dd[with(dd, order(-z, b)), ], times = 100000)
median 115.872

4
방법이 가장 느린 경우 성능 비교를 추가하는 것은 이상합니다 ... 어쨌든 4 행에서 벤치 마크를 사용하는 것의 가치가 의심 스럽습니다.data.frame
MichaelChirico

5

오래전의 기계식 카드 분류기와 마찬가지로, 가장 중요하지 않은 키를 기준으로 정렬 한 후 다음으로 가장 중요한 키를 기준으로 정렬합니다. 라이브러리가 필요하지 않으며 여러 키와 오름차순 및 내림차순 키 조합으로 작동합니다.

 dd <- dd[order(dd$b, decreasing = FALSE),]

이제 가장 중요한 키를 수행 할 준비가되었습니다. 정렬은 안정적이며 가장 중요한 키의 관계는 이미 해결되었습니다.

dd <- dd[order(dd$z, decreasing = TRUE),]

이것은 가장 빠르지는 않지만 확실하고 간단합니다.


4

rgr패키지를 사용하는 또 다른 대안 :

> library(rgr)
> gx.sort.df(dd, ~ -z+b)
    b x y z
4 Low C 9 2
2 Med D 3 1
1  Hi A 8 1
3  Hi A 9 1

4

열 이름이 매번 다를 수있는 n 개의 열에 대한 주문 프로세스를 자동화하려고 할 때 위의 솔루션으로 어려움을 겪고있었습니다. 에서 매우 유용한 기능을 찾았습니다.psych패키지 에서이 간단하게 수행 .

dfOrder(myDf, columnIndices)

어디 columnIndices 당신이 그들을 정렬 할 순서대로 하나 개 이상의 컬럼의 인덱스가 있습니다. 자세한 내용은 여기 :

'정신'패키지의 dfOrder 함수

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