Факторы в R: больше, чем раздражение?

Один из основных типов данных в R - это факторы. По моему опыту, факторы - это в основном боль, и я никогда не использую их. Я всегда конвертирую в персонажей. Странное чувство, будто я чего-то упускаю.

Есть ли какие-нибудь важные примеры функций, которые используют факторы в качестве группирующих переменных, где факторный тип данных становится необходимым? Существуют ли особые обстоятельства, при которых я должен использовать коэффициенты?

95
задан Christopher Bottoms 20 February 2015 в 19:50
поделиться

5 ответов

Вы должны использовать факторы. Да, они могут быть неприятны, но, по моей теории, 90% того, почему они неприятны, связано с тем, что в read.table и read.csv аргумент stringsAsFactors = TRUE по умолчанию (и большинство пользователей упускают эту тонкость). Я говорю, что они полезны, потому что пакеты подгонки моделей, такие как lme4, используют факторы и упорядоченные факторы для дифференцированной подгонки моделей и определения типа контрастов. А пакеты для построения графиков также используют их для группировки по. ggplot и большинство функций подгонки моделей преобразуют символьные векторы в факторы, так что результат тот же. Однако в итоге в коде появляются предупреждения:

lm(Petal.Length ~ -1 + Species, data=iris)

# Call:
# lm(formula = Petal.Length ~ -1 + Species, data = iris)

# Coefficients:
#     Speciessetosa  Speciesversicolor   Speciesvirginica  
#             1.462              4.260              5.552  

iris.alt <- iris
iris.alt$Species <- as.character(iris.alt$Species)
lm(Petal.Length ~ -1 + Species, data=iris.alt)

# Call:
# lm(formula = Petal.Length ~ -1 + Species, data = iris.alt)

# Coefficients:
#     Speciessetosa  Speciesversicolor   Speciesvirginica  
#             1.462              4.260              5.552  

Warning message: In model.matrix.default(mt, mf, contrasts) :

переменная Species преобразована в фактор

Одна сложная вещь - весь бит drop=TRUE. В векторах это хорошо работает для удаления уровней факторов, которых нет в данных. Например:

s <- iris$Species
s[s == 'setosa', drop=TRUE]
#  [1] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [11] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [21] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [31] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [41] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# Levels: setosa
s[s == 'setosa', drop=FALSE]
#  [1] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [11] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [21] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [31] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [41] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# Levels: setosa versicolor virginica

Однако, с data.frames, поведение [.data.frame() отличается: смотрите это письмо или ?"[.data.frame". Использование drop=TRUE на data.frames не работает так, как вы могли бы себе представить:

x <- subset(iris, Species == 'setosa', drop=TRUE)  # susbetting with [ behaves the same way
x$Species
#  [1] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [11] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [21] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [31] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [41] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# Levels: setosa versicolor virginica

К счастью, вы можете легко отбросить факторы с помощью droplevels() для отбрасывания неиспользуемых уровней факторов для отдельного фактора или для каждого фактора в data. frame (начиная с R 2.12):

x <- subset(iris, Species == 'setosa')
levels(x$Species)
# [1] "setosa"     "versicolor" "virginica" 
x <- droplevels(x)
levels(x$Species)
# [1] "setosa"

Вот как сделать так, чтобы выбранные вами уровни не попадали в легенды ggplot.

Внутри, factors - это целые числа с вектором символов уровня атрибута (см. attributes(iris$Species) и class(attributes(iris$Species)$levels)), что является чистым. Если бы вам нужно было изменить имя уровня (и вы использовали символьные строки), это было бы гораздо менее эффективной операцией. А я часто меняю имена уровней, особенно для ggplot легенд. Если вы подделываете факторы с векторами символов, есть риск, что вы измените только один элемент и случайно создадите отдельный новый уровень.

49
ответ дан 24 November 2019 в 05:53
поделиться

Факторы прекрасны, когда кто-то выполняет статистический анализ и фактически исследует данные. Однако до этого, когда вы читаете, очищаете, устраняете неполадки, объединяете и обычно манипулируете данными, факторы становятся полной болью. Совсем недавно, как и в последние несколько лет, многие функции были улучшены, чтобы лучше справляться с факторами. Например, с ними хорошо играет rbind. Я до сих пор считаю, что оставлять пустые уровни после функции подмножества совершенно неудобно.

#drop a whole bunch of unused levels from a whole bunch of columns that are factors using gdata
require(gdata)
drop.levels(dataframe)

Я знаю, что перекодировать уровни фактора и перенастроить метки несложно, а также есть замечательные способы изменить порядок уровней. Мой мозг просто не может их запомнить, и мне приходится переучивать его каждый раз, когда я его использую. Перекодирование должно быть намного проще, чем оно есть на самом деле.

Строковые функции R довольно просты и логичны в использовании. Поэтому при манипулировании я обычно предпочитаю персонажей факторам.

13
ответ дан 24 November 2019 в 05:53
поделиться

Какой язвительный заголовок!

Я считаю, что многие оценочные функции позволяют вам использовать факторы, чтобы легко определять фиктивные переменные ... но я не использую их для этого.

Я использую их, когда у меня очень большие векторы символов с небольшим количеством уникальных наблюдений. Это может сократить потребление памяти, особенно если строки в векторе символов длиннее.

PS - Я шучу по поводу названия. Я видел твой твит. ; -)

6
ответ дан 24 November 2019 в 05:53
поделиться

упорядоченные факторы - это круто, если я люблю апельсины и ненавижу яблоки, но не возражаю против винограда, мне не нужно управлять каким-то странным индексом, чтобы сказать это:

d <- data.frame(x = rnorm(20), f = sample(c("apples", "oranges", "grapes"), 20, replace = TRUE, prob = c(0.5, 0.25, 0.25)))
d$f <- ordered(d$f, c("apples", "grapes", "oranges"))
d[d$f >= "grapes", ]
30
ответ дан 24 November 2019 в 05:53
поделиться

tapplyaggregate) полагаются на факторы. Отношение информации к затраченным усилиям у этих функций очень высокое.

Например, в одной строке кода (вызов tapply ниже) можно получить среднюю цену бриллиантов по огранке и цвету:

> data(diamonds, package="ggplot2")

> head(dm)

   Carat     Cut    Clarity Price Color
1  0.23     Ideal     SI2   326     E
2  0.21   Premium     SI1   326     E
3  0.23      Good     VS1   327     E


> tx = with(diamonds, tapply(X=Price, INDEX=list(Cut=Cut, Color=Color), FUN=mean))

> a = sort(1:diamonds(tx)[2], decreasing=T)  # reverse columns for readability

> tx[,a]

         Color
Cut         J    I    H    G    F    E    D
Fair      4976 4685 5136 4239 3827 3682 4291
Good      4574 5079 4276 4123 3496 3424 3405
Very Good 5104 5256 4535 3873 3779 3215 3470
Premium   6295 5946 5217 4501 4325 3539 3631
Ideal     4918 4452 3889 3721 3375 2598 2629
-2
ответ дан 24 November 2019 в 05:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: