질문자 :Christopher DuBois
여러 열을 기준으로 data.frame을 정렬하고 싶습니다. 예를 들어 아래의 data.frame을 사용하여 z
열(내림차순)을 기준으로 b
열(오름차순)을 기준으로 정렬하고 싶습니다.
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 bxyz 1 Hi A 8 1 2 Med D 3 1 3 Hi A 9 1 4 Low C 9 2
order()
함수를 직접 사용할 수 있습니다 example(order)
코드의 맨 위에서 바로 트릭을 사용하는 이 간단한 답변을 참조하세요.
R> dd[with(dd, order(-z, b)), ] bxyz 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]), ] bxyz 4 Low C 9 2 2 Med D 3 1 1 Hi A 8 1 3 Hi A 9 1 R>
열의 이름을 사용하는 대신(더 쉽고/더 직접적인 액세스를 위해 with()
Dirk Eddelbuettel당신의 선택
-
base
에서 order
-
arrange
에서 dplyr
-
setorder
및 setorderv
에서 data.table
-
arrange
에서 plyr
-
taRifx
에서 sort
-
doBy
orderBy
-
sortData
의 데이터 Deducer
의존성이 없는 것이 중요하지 않다면 대부분 dplyr
또는 data.table
솔루션을 사용해야 합니다. base::order
최근에 CRAN 패키지에 sort.data.frame을 추가하여 여기에 설명된 대로 클래스 호환이 가능 하도록 했습니다. 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 )
이 기능의 원저자 중 한 명이면 저에게 연락하십시오. 공개 도메인에 대한 논의는 여기: https://chat.stackoverflow.com/transcript/message/1094290#1094290
위의 스레드에서 Hadley가 지적한 대로 plyr
arrange()
함수를 사용할 수도 있습니다.
library(plyr) arrange(dd,desc(z),b)
벤치마크: 많은 충돌이 있었기 때문에 새 R 세션에서 각 패키지를 로드했습니다. 특히 doBy 패키지를 로드하면 sort
가 "The following object(s) are masked from 'x (position 17)': b, x, y, z"를 반환하고 Deducer 패키지를 로드하면 Kevin의 sort.data.frame
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))
(선은 하위 사분위수에서 상위 사분위수까지 연장되며 점은 중앙값입니다)
이러한 결과와 단순성 대 속도의 무게를 감안할 때, 나는 plyr
패키지 arrange
하는 데 고개를 끄덕여야 합니다. 간단한 구문을 가지고 있지만 복잡한 기계가 있는 기본 R 명령만큼 빠릅니다. 일반적으로 뛰어난 Hadley Wickham 작품. sort(object)
의해 호출되는 표준 R 명명법을 위반한다는 것입니다. 하지만 위에 링크된 질문에서 논의된 문제로 인해 Hadley가 그렇게 한 이유를 이해합니다.
Ari B. FriedmanDirk의 대답은 훌륭합니다. 또한 인덱싱에 사용되는 구문의 키 차이를 강조 data.frame
들과 data.table
들 :
## 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
다양한 위치에 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)]
아주 작은 차이지만 언젠가는 목을 아낄 수 있습니다. 이 질문에 대한 다양한 답변을 평가할 때 변수 이름의 반복 횟수를 결정 기준 중 하나로 고려하십시오. 일부 답변에는 반복 횟수가 꽤 많고 다른 답변에는 반복되지 않습니다.
Matt Dowle여기에 훌륭한 답변이 많이 있지만 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) bxyz 1 Low C 9 2 2 Med D 3 1 3 Hi A 8 1 4 Hi A 9 1
BenR 패키지 data.table
은 직관적인 구문을 사용하여 data.tables의 빠르고 메모리 효율적인 순서를 제공합니다(Matt가 그의 답변에서 이 부분을 아주 훌륭하게 강조한 부분). 그 이후로 상당히 많은 개선과 새로운 기능인 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.table
의 DT[order(...)]
구문은 가장 빠른 다른 메서드( dplyr
)보다 ~10배 빠르지만 dplyr 과 동일한 양의 메모리를 dplyr
합니다.
data.table
의 setorder()
는 0.4GB 추가 메모리를 사용 하면서 가장 빠른 다른 방법( dplyr
)보다 ~14배 빠릅니다. dat
는 이제 우리가 필요로 하는 순서대로 되어 있습니다(참조로 업데이트됨).
data.table 기능:
속도:
메모리:
시간의 대부분은, 우리는 재정렬 후 원래 data.frame 또는 data.table이 필요하지 않습니다. 즉, 일반적으로 결과를 동일한 객체에 다시 할당합니다. 예를 들면 다음과 같습니다.
DF <- DF[order(...)]
문제는 이것이 원래 개체의 최소 두 배(2x) 메모리가 필요하다는 것입니다. 따라서 메모리 효율성 을 높이기 위해 data.table setorder()
함수도 제공합니다.
setorder()
는 추가 복사본을 만들지 않고 by reference
( in-place )로 data.tables를 재정렬합니다. 하나의 열 크기와 동일한 추가 메모리만 사용합니다.
다른 특징들:
integer
, logical
, numeric
, character
및 심지어 bit64::integer64
유형을 지원합니다.
factor
, Date
, POSIXct
등의 클래스는 integer
/ numeric
유형이므로 지원됩니다.
기본 R에서는 -
를 사용하여 해당 열을 내림차순으로 정렬할 수 없습니다. -xtfrm(.)
을 사용해야 합니다.
그러나 data.table 에서는 dat[order(-x)]
또는 setorder(dat, -x)
있습니다.
ArunR 위키의 팁 섹션에 게시 된 Kevin Wright의 이 (매우 유용한) 기능을 사용하면 쉽게 달성할 수 있습니다.
sort(dd,by = ~ -z + b) # bxyz # 4 Low C 9 2 # 2 Med D 3 1 # 1 Hi A 8 1 # 3 Hi A 9 1
Christopher DuBoisdata.frame
A
x
라는 열을 사용하여 정렬하려고 한다고 가정합니다. 정렬 된 전화 data.frame
newdata
newdata <- A[order(-A$x),]
오름차순을 원하면 "-"
를 아무 것도 사용하지 마십시오. 당신은 같은 것을 가질 수 있습니다
newdata <- A[order(-A$x, A$y, -A$z),]
여기서 x
와 z
data.frame
A
일부 열입니다. x
내림차순, y
오름차순 및 z
data.frame
A
를 정렬하는 것을 의미합니다.
Khayelihle또는 패키지 doBy를 사용할 수 있습니다.
library(doBy) dd <- orderBy(~-z+b, data=dd)
George DontasSQL이 자연스럽게 이해되면 sqldf
패키지는 Codd가 의도한 대로 ORDER BY
malecki또는 Deducer 패키지를 사용하여
library(Deducer) dd<- sortData(dd,c("z","b"),increasing= c(FALSE,TRUE))
Ian Fellows프로그래밍 방식으로 정렬하는 방법에 대해 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
수식을 사용하여 식을 평가하는 환경도 캡처하므로 수식을 사용하는 것이 좋습니다.
데이터 테이블
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
info_seekeR나는 오랫동안 나를 혼란스럽게 한 다음 예를 통해 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
가 data frame data
에서 Age
라는 열이 아니라 vector Age
정렬되기 때문입니다.
이를 확인하려면 위의 벡터를 사용하지 않고 열 이름이 약간 다른 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)
age
라는 벡터가 없기 때문에 order
줄 구조는 더 이상 작동하지 않습니다.
databyage = my.data[order(age),]
다음 줄은 my.data 의 열 age
을 my.data
order
정렬되기 때문에 작동합니다.
databyage = my.data[order(my.data$age),]
오랫동안 이 예제에 대해 얼마나 혼란스러워했는지 감안할 때 이것이 게시할 가치가 있다고 생각했습니다. 이 게시물이 스레드에 적합하지 않다고 판단되면 삭제할 수 있습니다.
편집: 2014년 5월 13일
다음은 열 이름을 지정하지 않고 모든 열을 기준으로 데이터 프레임을 정렬하는 일반적인 방법입니다. 아래 코드는 왼쪽에서 오른쪽으로 또는 오른쪽에서 왼쪽으로 정렬하는 방법을 보여줍니다. 모든 열이 숫자인 경우 작동합니다. 문자 열을 추가하여 시도하지 않았습니다.
나는 두 달 전에 다른 사이트의 오래된 게시물에서 do.call
지금 그 게시물을 옮길 수 있을지 확신이 서지 않습니다. R
data.frame
을 주문하기 위한 첫 번째 히트입니다. 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
Mark MillerDirk의 대답은 좋지만 정렬을 유지해야 하는 경우 해당 데이터 프레임의 이름에 정렬을 다시 적용하고 싶을 것입니다. 예제 코드 사용:
dd <- dd[with(dd, order(-z, b)), ]
Andrewdplyr의 Arrange()는 내가 가장 좋아하는 옵션입니다. 파이프 연산자를 사용하고 가장 중요하지 않은 측면에서 가장 중요한 측면으로 이동
dd1 <- dd %>% arrange(z) %>% arrange(desc(x))
Kaden Killpack완전성을 위해 열 번호로 정렬하는 것에 대해 많이 언급되지 않았기 때문에... 종종 바람직하지 않다고 주장할 수 있지만(열의 순서가 변경되어 오류가 발생할 수 있기 때문에) 일부 특정 상황(예: 빠른 작업이 필요하고 열의 순서 변경 위험이 없는 경우)에서는 특히 많은 수의 열을 처리할 때 가장 합리적인 방법일 수 있습니다.
이 경우 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 ## (...)
Dominic Comtois오래 전의 기계식 카드 분류기와 마찬가지로 먼저 가장 중요하지 않은 키로 정렬한 다음 다음으로 중요한 키로 정렬합니다. 라이브러리가 필요하지 않으며 원하는 수의 키와 오름차순 및 내림차순 키의 조합으로 작동합니다.
dd <- dd[order(dd$b, decreasing = FALSE),]
이제 가장 중요한 키를 수행할 준비가 되었습니다. 정렬이 안정적이고 가장 중요한 키의 모든 연결이 이미 해결되었습니다.
dd <- dd[order(dd$z, decreasing = TRUE),]
이것은 가장 빠르지 않을 수 있지만 확실히 간단하고 신뢰할 수 있습니다.
Rick완전성을 위해: BBmisc
패키지 sortByCol()
함수를 사용할 수도 있습니다.
library(BBmisc) sortByCol(dd, c("z", "b"), asc = c(FALSE, TRUE)) bxyz 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
Lars Kotthoff매번 열 이름이 다를 수 있는 n개의 열에 대한 주문 프로세스를 자동화하려고 할 때 위의 솔루션으로 어려움을 겪고 있었습니다. psych
패키지에서 간단한 방식으로 이 작업을 수행하는 데 매우 유용한 기능을 찾았습니다.
dfOrder(myDf, columnIndices)
여기서 columnIndices
는 정렬하려는 순서대로 하나 이상의 열에 대한 인덱스입니다. 추가 정보:
'psych' 패키지의 dfOrder 함수
AHegdergr
패키지를 사용하는 또 다른 대안:
> library(rgr) > gx.sort.df(dd, ~ -z+b) bxyz 4 Low C 9 2 2 Med D 3 1 1 Hi A 8 1 3 Hi A 9 1
Stéphane Laurent출처 : http:www.stackoverflow.com/questions/1296646/how-to-sort-a-dataframe-by-multiple-columns