프레임 - r 알파벳 순서




여러 칼럼으로 데이터 프레임을 정렬하는 방법은 무엇입니까? (12)

당신의 선택

  • base 로부터의 order
  • dplyr 에서 arrange dplyr
  • setordersetorderv from data.table
  • plyr 로부터 arrange plyr
  • taRifx 에서 sort
  • doBy orderBy
  • sortDataDeducer

대부분 의존성이 중요하지 않다면 dplyr 또는 data.table 솔루션을 사용해야 base::order .이 경우 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 )

이 기능의 원저자라면 저에게 연락하십시오. public domaininess에 대한 토론은 http://chat.stackoverflow.com/transcript/message/1094290#1094290 있습니다.

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

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

벤치 마크 : 충돌이 많았 기 때문에 각 패키지를 새로운 R 세션에로드했습니다. 특히 doBy 패키지를로드하면 sort 가 "x (위치 17) '에서 마스크 된 다음 객체를 반환합니다. b, x, y, z"및 Deducer 패키지를로드하면 Kevin의 sort.data.frame 을 덮어 씁니다. 라이트 또는 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 단순성을 감안할 때 plyr 패키지arrange 하기 arrange 끄덕임을 plyr 합니다 . 그것은 간단한 문법을 ​​가지고 있지만, 복잡한 R 명령과 거의 비슷한 속도입니다. 일반적으로 화려한 해들리 위컴이 일합니다. 내 유일한 불만은 정렬 객체가 sort(object) 의해 호출되는 표준 R 명명법을 어기는 것이지만, 왜 해들리가 위의 질문에서 논의 된 문제로 인해 그렇게했는지 이해합니다.

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
    b x y z
1  Hi A 8 1
2 Med D 3 1
3  Hi A 9 1
4 Low C 9 2

Dirk의 대답은 좋지만, 계속 유지해야하는 경우 데이터 프레임의 이름에 다시 정렬을 적용하려고합니다. 예제 코드 사용 :

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

SQL이 자연스럽게 사용자에게 제공되면 sqldf는 Codd가 의도 한대로 ORDER BY를 처리합니다.


dplyer의 arrange ()가 가장 좋아하는 옵션입니다. 파이프 연산자를 사용하여 가장 중요하지 않은 부분부터 가장 중요한 부분으로 이동하십시오.

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

더크의 대답은 훌륭합니다. 또한 data.tabledata.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 여러 위치에보고하고 어떻게 든 (어떻게 지구상에서?) 결국 이것으로 끝납니다 :

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

그것은 당신이 의미하는 바가 아니지만 당신이 그것을 빨리했고 비슷한 코드의 페이지에 자리 잡았 기 때문에 그것을 발견하지 못했습니다. R은 그것이 당신이 의미하는 바라고 생각하기 때문에 코드는 넘어지지 않습니다 (경고도 오류도 없음). 보고서를 읽는 사람이라면 누구나 그것을 볼 수 있길 바랄 것입니다. 그러나 그렇지 않을 수도 있습니다. 프로그래밍 언어로 많은 작업을한다면이 상황이 모두 친숙 할 수 있습니다. 그것은 당신이 말할 수있는 "오타"였습니다. 나는 당신의 상사에게 말할 "오타"를 고쳐 줄 것이다.

data.table 우리는 이와 같은 작은 세부 사항에 대해 우려하고 있습니다. 변수 이름을 두 번 입력하는 것을 피하기 위해 간단한 작업을 수행했습니다. 아주 간단합니다. i 이미 dd 프레임 안에서 자동으로 평가된다. 당신은 전혀 필요 없어.

대신에

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

그냥

dd[order(-z, b)]

그리고 대신에

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

그냥

quarterlyreport[order(-z,b)]

아주 작은 차이지만 언젠가 목을 살릴 수도 있습니다. 이 질문에 대한 다른 대답을 검토 할 때 변수 이름의 반복을 계산 기준으로 삼는 것이 좋습니다. 일부 답변에는 반복이 많으며 다른 답변에는 없음이 있습니다.


또는 Deducer 패키지를 사용합니다.

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

매번 컬럼 이름이 다를 수있는 n 개의 컬럼에 대한 주문 프로세스를 자동화하고 싶을 때 위의 솔루션으로 어려움을 겪고있었습니다. psych 패키지에서 직접적으로 도움이되는 유용한 기능을 발견했습니다.

dfOrder(myDf, columnIndices)

여기서 columnIndices 는 정렬하려는 순서대로 하나 이상의 열에 대한 색인입니다. 자세한 내용은 여기 :

'정신'패키지의 dfOrder 기능


애드온 도구를 사용하지 않고 직접 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() 더 쉽고 / 더 직접적인 액세스를 위해 with() 를 사용하는 것).


예전의 기계식 카드 분류기와 마찬가지로 가장 중요도가 낮은 키부터 우선 순위 순으로 정렬 한 다음 가장 중요한 순차 정렬과 같습니다. 라이브러리가 필요하지 않으며 임의의 수의 키와 오름차순 및 내림차순 키 조합으로 작동합니다.

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

이제 우리는 가장 중요한 열쇠를 할 준비가되었습니다. 정렬이 안정적이고 가장 중요한 키의 모든 연결이 이미 해결되었습니다.

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

이것은 가장 빠를 수는 없지만 간단하고 신뢰할 수 있습니다.


완벽을 기하기 위해 BBmisc 패키지의 sortByCol() 함수를 사용할 수도 있습니다.

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

프로그래밍 방식으로 정렬하는 방법에 대한 OP에 추가 된 주석에 대한 응답으로 :

dplyrdata.table

library(dplyr)
library(data.table)

디 핑거

arrange 위한 표준 평가판 인 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

data.frame A 있고 x 내림차순이라는 열을 사용하여 정렬하려고한다고 가정합니다. 정렬 된 newdata 호출합니다.

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

오름차순을 원할 경우 "-" 를 아무것도 사용하지 마십시오. 너는 비슷한 것을 가질 수있다.

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

여기서 xzdata.frame A 일부 열입니다. 이것은 data.frame Ax 내림차순, y 오름차순 및 z 내림차순으로 정렬하는 것을 의미합니다.





r-faq