sort()는 벡터의 값을 정렬합니다
평범한 벡터라면 sort()는 기대한 대로 동작합니다 - 값을 오름차순으로 반환하며 원본은 그대로입니다:
알아 둘 만한 옵션이 두 가지 있습니다. decreasing = TRUE는 방향을 뒤집습니다. 그리고 sort()는 기본적으로 NA 값을 조용히 제거 합니다 - sort(c(3, NA, 1))은 1 3만 반환합니다. 결측값이 정렬 후에도 남아야 한다면 어디에 둘지 지정하세요: sort(x, na.last = TRUE)는 정렬된 값들 뒤에 결측값을 배치해 유지합니다.
여기까지는 당연한 이야기입니다. 흥미로운 부분은 sort()가 데이터 프레임에는 왜 잘못된 도구인가입니다.
order()는 위치를 반환합니다 - 사고의 전환
sort()는 "정렬된 값이 무엇인가?"에 답합니다. order()는 다른 질문에 답합니다: "값을 순서대로 보려면 어떤 위치 를 방문해야 하는가?"
order(times)를 지시문처럼 읽으세요: 가장 작은 값은 2번 위치에, 그다음은 4번, 그다음 1번, 그다음 3번에 있습니다. 이 지시대로 인덱싱하면 - times[order(times)] - sort(times)와 정확히 같은 결과가 나옵니다.
이것이 왜 중요할까요? 데이터 프레임의 한 행은 함께 움직여야 하는 값들의 팀 이기 때문입니다. sort()로 time 열만 정렬하면 그 열만 재배열되고 동료들은 뒤에 남아 모든 행이 뒤죽박죽이 됩니다. 대신 order()는 행 위치를 주고, 그 위치를 대괄호의 행 자리에 넣으면 행 전체 가 움직입니다:
Ben의 9.8이 Ben의 이름을 그대로 달고 도착합니다. 이것이 기법의 전부이며, base R에서 데이터 프레임을 정렬하는 바로 그 관용구입니다: df[order(df$column), ]. (출력된 행 라벨 2 4 1 3은 함께 따라온 원래 행 번호입니다. 무해합니다.)
내림차순과 다중 열 정렬
수치형 내림차순 정렬에는 열에 음수 부호를 붙이세요 - -time을 오름차순으로 정렬하는 것이 곧 time을 내림차순으로 정렬하는 것입니다. 그리고 order()는 여러 열을 받습니다. 앞쪽이 우선이고 뒤쪽이 동점을 처리합니다:
두 번째 호출은 부서를 알파벳순으로 정렬하고, 각 부서 안에서 급여를 높은 순으로 정렬합니다. 음수화 기법은 숫자에만 통합니다 - 문자형 열에 -df$name을 쓰면 오류입니다. 텍스트를 내림차순으로 정렬하려면 order(df$name, decreasing = TRUE)를 쓰세요(이 옵션은 모든 정렬 키를 한꺼번에 뒤집습니다).
rank()는 세 번째 형제입니다
지나가는 김에 살펴보면, rank(x)는 또 다른 질문에 답합니다 - "각 값은 몇 번째인가?" - 아무것도 옮기지 않은 채로요:
sort()는 정렬된 값을, order()는 방문할 위치를, rank()는 제자리에서의 각 값의 순위를 줍니다. 사람들은 order()와 rank()를 늘 혼동합니다. 둘이 서로의 역치환(inverse permutation)이라는 점에 주목하고, 말 그대로 순위가 필요할 때만(리더보드, 백분위수) rank()를 쓰세요.
dplyr 방식: arrange()
dplyr의 arrange()는 order() 절차 전체를 하나의 동사로 감쌉니다 - 열이 정렬 키이고 desc()가 방향을 뒤집습니다(정적 예제입니다. 샌드박스는 base R만 실행합니다):
library(dplyr)
runners |> arrange(time)
staff |> arrange(dept, desc(salary))
대괄호도, $도, 음수화 기법도 필요 없습니다 - desc()는 문자형 열에서도 동작합니다. 알아 둘 만한 동작 차이 하나: arrange()는 방향과 무관하게 NA 값을 끝에 놓는데, base R의 order()도 기본값이 na.last = TRUE입니다. arrange()가 filter() 등과 어떻게 연결되는지는 dplyr 입문을 참고하세요.
문자 정렬에는 날카로운 모서리가 있습니다
텍스트를 정렬할 때 주의할 점이 두 가지 있습니다. 첫째, 텍스트로 저장된 숫자는 텍스트로 정렬됩니다 - 문자 비교는 기호를 하나씩 비교합니다:
"10"이 "2"보다 앞서는 이유는 비교가 첫 기호에서 끝나기 때문입니다: "1" < "2". 숫자로 된 열이 이상하게 정렬된다면 거의 확실히 문자형으로 저장된 것입니다 - 먼저 as.numeric()으로 변환하세요(지저분한 CSV 임포트 후에 자주 생기는 일입니다).
둘째, 텍스트 정렬 순서는 시스템 로케일 에 따라 달라집니다 - 강세 부호, 대소문자, 비라틴 문자는 여러분의 노트북과 C 로케일의 서버에서 다르게 정렬될 수 있습니다. 여러 기계에서 동일해야 하는 정렬 결과라면 로케일을 명시적으로 설정하거나 정규화된 키로 정렬해야 합니다.
핵심 정리
sort(x)는 벡터의 값을 정렬합니다.decreasing = TRUE가 방향을 뒤집고,na.last = TRUE가 아니면NA는 제거됩니다.order(x)는 위치를 반환하며,df[order(df$x), ]가 데이터 프레임 정렬을 위한 대표 base R 관용구입니다.- 다중 열:
order(df$a, -df$b). 내림차순을 위한 음수화는 숫자에만 통합니다. rank()는 재배열 없이 순위를 줍니다 -order()의 대체재가 아닙니다.- dplyr의
arrange(dept, desc(salary))는 구두점이 더 적은 같은 정렬입니다. - 텍스트에서는
"10"이"2"보다 앞섭니다 - 열 타입을 확인하세요.
다음 주제: table(), tapply(), aggregate(), 그리고 dplyr의 group_by()로 행을 그룹 요약으로 압축하기.
자주 묻는 질문
R에서 특정 열을 기준으로 데이터 프레임을 정렬하려면 어떻게 하나요?
행 대괄호 안에서 order()를 사용합니다: df[order(df$price), ]. order()는 정렬된 순서의 행 위치를 반환하고, 그 값으로 인덱싱하면 데이터 프레임 전체가 재배열됩니다. 여기서 sort()는 쓸 수 없습니다 - 한 벡터의 값만 정렬해 다른 열들과의 연결이 끊어지기 때문입니다.
R에서 sort()와 order()의 차이는 무엇인가요?
sort(x)는 x의 값을 정렬해 반환합니다. order(x)는 x를 정렬된 상태로 만들어 주는 위치(인덱스)를 반환하는데, 이것이 특정 열을 기준으로 데이터 프레임 전체를 정렬할 때 필요한 값입니다: df[order(df$x), ].
R에서 내림차순으로 정렬하려면 어떻게 하나요?
벡터라면 sort(x, decreasing = TRUE)입니다. 데이터 프레임이라면 df[order(-df$x), ](수치형 열에 음수 부호)이나 df[order(df$x, decreasing = TRUE), ]인데, 후자는 음수화가 통하지 않는 문자형 열에도 동작합니다. dplyr에서는 arrange(df, desc(x))입니다.
R에서 여러 열을 기준으로 정렬하려면 어떻게 하나요?
order()에 모두 전달합니다: df[order(df$dept, -df$salary), ]는 부서로 정렬한 뒤 각 부서 안에서 급여를 내림차순으로 정렬합니다. 앞쪽 인자가 1차 정렬 키이고 뒤쪽 인자가 동점을 처리합니다. dplyr에서는 arrange(df, dept, desc(salary))입니다.