값 순서를 변경하지 않고 요인 수준 재정렬


124

일부 수치 변수와 일부 범주 factor변수 가있는 데이터 프레임이 있습니다 . 이러한 요인에 대한 수준의 순서는 내가 원하는 방식이 아닙니다.

numbers <- 1:4
letters <- factor(c("a", "b", "c", "d"))
df <- data.frame(numbers, letters)
df
#   numbers letters
# 1       1       a
# 2       2       b
# 3       3       c
# 4       4       d

레벨의 순서를 변경하면 문자가 더 이상 해당 숫자와 함께 표시되지 않습니다 (이 시점부터 내 데이터는 총 넌센스입니다).

levels(df$letters) <- c("d", "c", "b", "a")
df
#   numbers letters
# 1       1       d
# 2       2       c
# 3       3       b
# 4       4       a

레벨 순서 를 변경하고 싶기 때문에 플로팅 할 때 막대가 원하는 순서로 표시되며 이는 기본 알파벳 순서와 다를 수 있습니다.


1
crangos가 질문에서 보여주는 것처럼 누군가 레벨 (...) 할당이 데이터 프레임의 항목 순서를 변경하는 이유에 대한 힌트를 줄 수 있습니까? 그것은 매우 직관적이지 않고 나에게 바람직하지 않은 것 같습니다. 나는 오늘 이것으로 인한 문제를 디버깅하는데 시간을 보냈다. 나는 내가 볼 수없는이 행동에 대한 이유가 있거나 그 이유에 대한 합리적인 설명이있을 수 있다고 생각합니다.
Anton

답변:


120

다음 levels인수를 사용하십시오 factor.

df <- data.frame(f = 1:4, g = letters[1:4])
df
#   f g
# 1 1 a
# 2 2 b
# 3 3 c
# 4 4 d

levels(df$g)
# [1] "a" "b" "c" "d"

df$g <- factor(df$g, levels = letters[4:1])
# levels(df$g)
# [1] "d" "c" "b" "a"

df
#   f g
# 1 1 a
# 2 2 b
# 3 3 c
# 4 4 d

1
감사합니다. 이상한 이유로 ggplot은 이제 범례의 순서를 올바르게 변경했지만 플롯에서는 변경하지 않았습니다. 기묘한.
crangos

7
ggplot2는 레벨 순서 (위 참조)와 데이터 프레임 값의 순서를 모두 변경해야했습니다. df <
-df

@crangos, 저는 ggplot이 알파벳순 수준의 순서를 사용하고 때로는 사용자 지정 요인 수준을 무시한다고 생각합니다. 확인하고 버전 번호를 포함하십시오.
smci

22

기록을 위해 좀 더

## reorder is a base function
df$letters <- reorder(df$letters, new.order=letters[4:1])

library(gdata)
df$letters <- reorder.factor(df$letters, letters[4:1])

유용한 Relevelcombine_factor 도 찾을 수 있습니다 .


2
당신의 첫 번째 대답은 나를 위해 작동하지 않습니다. 그러나 이것은 작동합니다 :reorder(df$letters, seq(4,1))
Alex Holcombe

1
"재정렬"이 다른 데이터 세트가 아닌 한 데이터 세트에서 작동하는 매우 이상한 상황이 있습니다. 다른 데이터 세트에서는 "Error in tapply (X = X, INDEX = x, FUN = FUN, ...) : argument"X "is missing, with no default"오류가 발생합니다. 이 문제에 대한 해결책이 무엇인지 확실하지 않습니다. 데이터 세트간에 관련성있는 차이점을 찾을 수 없습니다.
CoderGuy123 2015

10

이 질문이 마지막으로 활성화 된 이후로 Hadley는 forcats요인 조작을위한 그의 새 패키지를 출시했으며이 질문이 엄청나게 유용하다는 것을 알게되었습니다. OP 데이터 프레임의 예 :

levels(df$letters)
# [1] "a" "b" "c" "d"

레벨을 반전하려면

library(forcats)
fct_rev(df$letters) %>% levels
# [1] "d" "c" "b" "a"

레벨을 더 추가하려면 :

fct_expand(df$letters, "e") %>% levels
# [1] "a" "b" "c" "d" "e"

그리고 더 많은 유용한 fct_xxx()기능.


여전히 사용할 수 있습니까?
Joshua Rosenberg 2016

1
다음과 같은 코드를 작성하고 싶습니다 df %>% mutate(letters = fct_rev(letters))..
jazzurro

9

따라서 R 어휘집에서 원하는 것은 주어진 요인 변수에 대한 레이블 만 변경 하는 것입니다 (즉, 데이터와 요인 수준 을 변경하지 않고 그대로 둡니다 ).

df$letters = factor(df$letters, labels=c("d", "c", "b", "a"))

데이터 또는 요인 스키마가 아닌 데이터 포인트-라벨 매핑 만 변경하려는 경우 (데이터 포인트가 개별 구간 또는 요인 값으로 구간 화되는 방식, 처음 만들 때 매핑이 원래 설정되는 방식을 아는 것이 도움이 될 수 있습니다. 요인.

규칙은 간단합니다.

  • 레이블은 인덱스 값에 의해 레벨에 매핑됩니다 (즉, 레벨 [2]의 값에는 레이블, 레이블 [2]가 지정됩니다).
  • 요인 수준은 levels 인수 를 통해 전달하여 명시 적으로 설정할 수 있습니다 . 또는
  • levels 인수에 값이 제공되지 않으면 전달 된 데이터 벡터에서 고유 한 결과 인 기본값이 사용 됩니다 ( 데이터 인수의 경우).
  • 레이블은 labels 인수를 통해 명시 적으로 설정할 수 있습니다. 또는
  • labels 인수에 값이 제공되지 않으면 레벨 벡터 인 기본값이 사용됩니다.

1
왜 이것이 수락 된 답변만큼 찬성표가 아닌지 모르겠습니다. 이것은 훨씬 더 유익합니다.
Rambatino 2014

12
이 방법을 사용하면 데이터의 레이블이 잘못 지정됩니다.
Nazer 2014 년

4
실제로 네, 이것으로 무엇을 해야할지 모르겠습니다. 대답은 플로팅을 위해 데이터를 잘못 분류하려는 것 같습니다. 으. 원본으로 되돌 렸습니다. 사용자는 조심
RAWR

7

R의 요인을 다루는 것은 매우 특이한 일입니다. 저는 인정해야합니다 ... 요인 수준을 재정렬하는 동안 기본 숫자 값을 재정렬하는 것은 아닙니다. 다음은 약간의 데모입니다.

> numbers = 1:4
> letters = factor(letters[1:4])
> dtf <- data.frame(numbers, letters)
> dtf
  numbers letters
1       1       a
2       2       b
3       3       c
4       4       d
> sapply(dtf, class)
  numbers   letters 
"integer"  "factor" 

이제이 인수를 숫자로 변환하면 다음을 얻을 수 있습니다.

# return underlying numerical values
1> with(dtf, as.numeric(letters))
[1] 1 2 3 4
# change levels
1> levels(dtf$letters) <- letters[4:1]
1> dtf
  numbers letters
1       1       d
2       2       c
3       3       b
4       4       a
# return numerical values once again
1> with(dtf, as.numeric(letters))
[1] 1 2 3 4

보시다시피 ... 레벨을 변경하면 수치가 아닌 레벨 만 변경됩니다 (누가 말할까요?). 그러나 factor@Jonathan Chang이 제안한대로 함수 를 사용하면 다른 일이 발생합니다. 숫자 값을 직접 변경합니다.

다시 한 번 오류가 발생 levels하고 있습니다 factor. 하지마 !!! 마십시오 하지 사용 levels또는 당신이 엉망 일을거야 (당신은 당신이 무엇인지 정확히 모르는 경우).

한 가지 제안 : R의 객체와 동일한 이름으로 객체의 이름을 지정하지 마십시오 ( dfF 분포의 밀도 함수, letters소문자 알파벳 문자 제공). 이 특별한 경우에, 당신의 코드는 결함이 없을 것입니다. 그러나 때때로 그것은 ... 그러나 이것은 혼란을 야기 할 수 있습니다. 그리고 우리는 그것을 원하지 않습니다, 그렇죠?!? =)

대신 다음과 같이 사용하십시오 (처음부터 다시 시작하겠습니다).

> dtf <- data.frame(f = 1:4, g = factor(letters[1:4]))
> dtf
  f g
1 1 a
2 2 b
3 3 c
4 4 d
> with(dtf, as.numeric(g))
[1] 1 2 3 4
> dtf$g <- factor(dtf$g, levels = letters[4:1])
> dtf
  f g
1 1 a
2 2 b
3 3 c
4 4 d
> with(dtf, as.numeric(g))
[1] 4 3 2 1

대신 및을 사용 data.frame하여 이름을 지정할 수도 있으며 결과는 정상입니다. 사실이 코드는 귀하가 게시 한 것과 동일하며 이름 만 변경됩니다. 이 부분 은 오류를 발생시키지 않지만 혼란 스러울 수 있습니다!dflettersgfactor(dtf$letter, levels = letters[4:1])

?factor설명서를 철저히 읽으십시오 ! factor(g, levels = letters[4:1])과 의 차이점은 무엇입니까 factor(g, labels = letters[4:1])? 유사한에서 무엇 levels(g) <- letters[4:1]g <- factor(g, labels = letters[4:1])?

ggplot 구문을 입력 할 수 있으므로 이에 대해 더 많은 도움을 드릴 수 있습니다!

건배!!!

편집하다:

ggplot2실제로 수준과 값을 모두 변경해야합니까? 흠 .. 이거 파낼 게요 ...


3

레벨이 특수 문자와 함께 숫자를 전달하는 문자열이 될 수있는 또 다른 경우를 추가하고 싶습니다.

df <- data.frame(x = c("15-25", "0-4", "5-10", "11-14", "100+"))

의 기본 수준 x은 다음과 같습니다.

df$x
# [1] 15-25 0-4   5-10  11-14 100+ 
# Levels: 0-4 100+ 11-14 15-25 5-10

여기에서 수준을 명시 적으로 작성하지 않고 숫자 값에 따라 요인 수준을 재정렬하려면 다음과 같이 할 수 있습니다.

library(gtools)
df$x <- factor(df$x, levels = mixedsort(df$x))

df$x
# [1] 15-25 0-4   5-10  11-14 100+ 
# Levels: 0-4 5-10 11-14 15-25 100+
as.numeric(df$x)
# [1] 4 1 2 3 5

앞으로 독자들에게 유용한 정보가 되길 바랍니다.


0

주어진 데이터 프레임의 요소를 재정렬하는 기능은 다음과 같습니다.

reorderFactors <- function(df, column = "my_column_name", 
                           desired_level_order = c("fac1", "fac2", "fac3")) {

  x = df[[column]]
  lvls_src = levels(x) 

  idxs_target <- vector(mode="numeric", length=0)
  for (target in desired_level_order) {
    idxs_target <- c(idxs_target, which(lvls_src == target))
  }

  x_new <- factor(x,levels(x)[idxs_target])

  df[[column]] <- x_new

  return (df)
}

용법: reorderFactors(df, "my_col", desired_level_order = c("how","I","want"))

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