Один из основных типов данных в R - это факторы. По моему опыту, факторы - это в основном боль, и я никогда не использую их. Я всегда конвертирую в персонажей. Странное чувство, будто я чего-то упускаю.
Есть ли какие-нибудь важные примеры функций, которые используют факторы в качестве группирующих переменных, где тип данных фактор становится необходимым? Есть ли особые обстоятельства, при которых мне следует использовать факторы?
r
language-design
internals
r-factor
JD Long
источник
источник
Ответы:
Вам следует использовать коэффициенты. Да , они могут быть боль, но моя теория в том , что 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
Одна хитрость - это целый
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.frame
s[.data.frame()
ведет себя иначе: см. Это письмо или?"[.data.frame"
. Использованиеdrop=TRUE
ondata.frame
s не работает так, как вы думаете: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()
чтобы отбросить неиспользуемые уровни факторов для отдельного фактора или для каждого фактора в adata.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
легенды.Внутренне
factor
s - это целые числа с вектором символов уровня атрибута (см.attributes(iris$Species)
Иclass(attributes(iris$Species)$levels)
), который является чистым. Если бы вам пришлось изменить имя уровня (и вы использовали символьные строки), это была бы гораздо менее эффективная операция. И я часто меняю названия уровней, особенно дляggplot
легенд. Если вы подделываете факторы с помощью символьных векторов, есть риск, что вы измените только один элемент и случайно создадите отдельный новый уровень.источник
stringsAsFactors
это не функция.Упорядоченные факторы - это здорово, если я люблю апельсины и ненавижу яблоки, но не возражаю против винограда, мне не нужно управлять каким-то странным индексом, чтобы сказать это:
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", ]
источник
d$f <- ordered(d$f, c("apples", "grapes", "oranges"))
? Я бы предположил, что он заказал их во фрейме данных, но после того, как я запустил эту строку и распечатал фрейм данных, ничего не изменилось. Это просто внутренний порядок, даже если напечатанный порядок не меняется?A
factor
наиболее похож на нумерованный тип в других языках. Его подходящее использование - для переменной, которая может принимать только одно из заданного набора значений. В этих случаях не все возможные допустимые значения могут присутствовать в каком-либо конкретном наборе данных, и «пустые» уровни точно это отражают.Рассмотрим несколько примеров. Для некоторых данных, которые были собраны по всей территории Соединенных Штатов, в качестве фактора следует указать штат. В данном случае имеет значение тот факт, что в конкретном штате не было собрано никаких дел. Могли быть данные из этого состояния, но случилось (по какой-то причине, которая может представлять интерес) их не было. Если бы родной город был собран, это не было бы фактором. Не существует заранее определенного набора возможных мест проживания. Если бы данные были собраны из трех городов, а не на национальном уровне, город был бы фактором: есть три варианта, которые были даны в начале, и если не было найдено соответствующих случаев / данных в одном из этих трех городов, это актуально.
Другие аспекты
factor
s, такие как предоставление способа задать произвольный порядок сортировки для набора строк, являются полезными вторичными характеристикамиfactor
s, но не являются причиной их существования.источник
Факторы прекрасны, когда кто-то проводит статистический анализ и фактически исследует данные. Однако до этого, когда вы читаете, очищаете, устраняете неполадки, объединяете и обычно манипулируете данными, факторы становятся полной болью. Совсем недавно, как и в последние несколько лет, многие функции были улучшены, чтобы лучше справляться с факторами. Например, с ними хорошо играет 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 довольно просты и логичны в использовании. Поэтому при манипулировании я обычно предпочитаю персонажей факторам.
источник
droplevels()
. И он не меняет порядок факторов по умолчанию.Какой язвительный титул!
Я считаю, что многие функции оценки позволяют вам использовать факторы, чтобы легко определять фиктивные переменные ... но я не использую их для этого.
Я использую их, когда у меня очень большие векторы символов с небольшим количеством уникальных наблюдений. Это может сократить потребление памяти, особенно если строки в векторе символов длиннее.
PS - Шучу по поводу названия. Я видел твой твит. ;-)
источник
?factor
R-2.6.0, в нем говорится: «Целочисленные значения хранятся в 4 байтах, тогда как каждая ссылка на символьную строку требует указателя размером 4 или 8 байтов». Вы бы сэкономили место при преобразовании в множитель, если бы символьной строке требовалось 8 байтов?N=100000
меня получилось 391,5 Кб против 391,8 Кб. Фактор требует немного больше памяти.Факторы - превосходный двигатель выдачи значков "уникальных случаев". Я много раз воссоздавал это плохо, и, несмотря на то, что иногда появляются несколько морщинок, они очень сильны.
library(dplyr) d <- tibble(x = sample(letters[1:10], 20, replace = TRUE)) ## normalize this table into an indexed value across two tables id <- tibble(x_u = sort(unique(d$x))) %>% mutate(x_i = row_number()) di <- tibble(x_i = as.integer(factor(d$x))) ## reconstruct d$x when needed d2 <- inner_join(di, id) %>% transmute(x = x_u) identical(d, d2) ## [1] TRUE
Если есть лучший способ выполнить эту задачу, я бы хотел его увидеть, я не вижу, чтобы эта возможность
factor
обсуждалась.источник
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
источник