Переупорядочить уровни фактора без изменения порядка значений
У меня есть кадр данных с некоторыми численными переменными и некоторыми категориальными переменными 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
Используйте аргумент 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
Ответ 2
еще несколько, только для записи
## 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])
Вы также можете найти Relevel и comb_factor.
Ответ 3
так что вы хотите, в R lexicon, изменить только метки для данной фактор-переменной (т.е. оставить данные, а также уровни факторов неизменными).
df$letters = factor(df$letters, labels=c("d", "c", "b", "a"))
учитывая, что вы хотите изменить только сопоставление данных на метку, а не данные или схему факторов (как привязки данных привязываются к отдельным ячейкам или значениям факторов, это может помочь узнать, как изначально установлено сопоставление, когда вы изначально создаете фактор.
правила просты:
- метки сопоставляются с уровнями по значению индекса (т.е. значение
на уровнях [2] дана метка, метка [2]);
- уровни факторов могут быть заданы явно, передав их через
аргумент уровней; или
- Если для аргумента уровней не указано значение, значение по умолчанию
значение, которое является результатом, вызывающим уникальное значение для вектора данных
(для аргумента данных);
- метки могут быть явно заданы с помощью аргумента меток; или
- Если для аргумента меток не указано значение, значение по умолчанию равно
используется только вектор уровней
Ответ 4
Работа с факторами в 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
. Не делай этого!!! Do not используйте levels
, иначе вы будете испортываться (если вы точно не знаете, что делаете).
<я > Предложение lil ': не называть ваши объекты с таким же именем, как объекты R (df
- функция плотности для распределения F, 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
df
и letters
вместо g
, и результат будет в порядке. На самом деле этот код идентичен тому, который вы опубликовали, только имена изменены. Эта часть factor(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, чтобы мы могли больше помочь вам в этом!
Ура!!!
Edit:
ggplot2
действительно требуется изменить оба уровня и значения? Хм... Я выкопаю этот...
Ответ 5
Поскольку этот вопрос был последним, Хэдли выпустил свой новый пакет 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()
.
Ответ 6
Я хочу добавить еще один случай, когда уровни могут быть строками, несущими числа вместе с некоторыми специальными символами: например, ниже пример
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
Надеюсь, это можно считать полезной информацией для будущих читателей.