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

일부 수치 변수와 일부 범주 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

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



답변

다음 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


답변

기록을 위해 좀 더

## 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 도 찾을 수 있습니다 .


답변

이 질문이 마지막으로 활성화 된 이후로 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()기능.


답변

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

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

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

규칙은 간단합니다.

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

답변

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실제로 수준과 값을 모두 변경해야합니까? 흠 .. 이거 파낼 게요 …


답변

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

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

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


답변

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

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"))