У меня есть фрейм данных, содержащий factor
. Когда я создаю подмножество этого subset
фрейма данных, используя или другую функцию индексации, создается новый фрейм данных. Однако factor
переменная сохраняет все свои исходные уровни, даже если / если они не существуют в новом кадре данных.
Это вызывает проблемы при выполнении граненых графиков или при использовании функций, основанных на факторных уровнях.
Какой самый короткий способ удалить уровни из фактора в новом фрейме данных?
Вот пример:
df <- data.frame(letters=letters[1:5],
numbers=seq(1:5))
levels(df$letters)
## [1] "a" "b" "c" "d" "e"
subdf <- subset(df, numbers <= 3)
## letters numbers
## 1 a 1
## 2 b 2
## 3 c 3
# all levels are still there!
levels(subdf$letters)
## [1] "a" "b" "c" "d" "e"
mydf <- droplevels(mydf)
предпочтительным является решение, предложенное Романом Луштриком и Томми О'Деллом ниже.Начиная с версии R 2.12, есть
droplevels()
функция.источник
factor()
заключается в том, что нет необходимости изменять исходный кадр данных или создавать новый постоянный кадр данных. Я могу обернутьdroplevels
вокруг установленного кадра данных и использовать его в качестве аргумента данных для функции решетки, и группы будут обрабатываться правильно.Если вы не хотите такого поведения, не используйте факторы, используйте вместо них векторы символов. Я думаю, что это имеет больше смысла, чем исправление вещей впоследствии. Попробуйте выполнить следующее перед загрузкой данных с помощью
read.table
илиread.csv
:Недостатком является то, что вы ограничены в алфавитном порядке. (изменить порядок - ваш друг по участкам)
источник
Это известная проблема, и один из возможного средства предусмотрено
drop.levels()
в GData пакета , где ваш пример становитсяТакже есть
dropUnusedLevels
функция в пакете Hmisc . Однако он работает только путем изменения оператора подмножества[
и здесь неприменим.Как следствие, прямой подход для каждого столбца прост
as.factor(as.character(data))
:источник
reorder
Параметрdrop.levels
функции стоит упомянуть: если у вас есть , чтобы сохранить первоначальный порядок ваших факторов, использовать егоFALSE
значение.Еще один способ сделать то же самое, но с
dplyr
Редактировать:
Также работает! Спасибо Agenis
источник
Для полноты картины , теперь есть и
fct_drop
вforcats
пакете http://forcats.tidyverse.org/reference/fct_drop.html .Он отличается от
droplevels
того, как он работает сNA
:источник
Вот еще один способ, который, я считаю, эквивалентен
factor(..)
подходу:источник
`[.factor`
метод, который имеетdrop
аргумент, и вы опубликовали это в 2009 году ...Это противно. Вот как я обычно это делаю, чтобы не загружать другие пакеты:
который получает вас:
Обратите внимание, что новые уровни заменят все, что занимает их индекс на старых уровнях (subdf $ letters), поэтому что-то вроде:
не сработает
Это очевидно не идеально, когда у вас много уровней, но для некоторых это быстро и легко.
источник
Глядя на код
droplevels
методов в исходном коде R, вы видите, что онfactor
работает. Это означает, что вы можете воссоздать столбец с помощьюfactor
функции.Ниже data.table способ отбрасывать уровни из всех столбцов факторов.
источник
data.table
путь будет что-то вродеfor (j in names(DT)[sapply(DT, is.factor)]) set(DT, j = j, value = factor(DT[[j]]))
[.data.table
вот способ сделать это
источник
Я написал вспомогательные функции для этого. Теперь, когда я знаю о drop.levels gdata, он выглядит примерно так же. Вот они ( отсюда ):
источник
Очень интересная ветка, мне особенно понравилась идея просто снова проанализировать выборку. Раньше у меня была похожая проблема, и я просто перешел на характер, а затем снова на фактор.
источник
factor(as.chracter(...))
работает, но просто менее эффективно и кратко, чемfactor(...)
. Кажется, строго хуже, чем другие ответы.К сожалению, factor () не работает при использовании rxDataStep из RevoScaleR. Я делаю это в два этапа: 1) Преобразование в символ и сохранение во временном внешнем фрейме данных (.xdf). 2) Преобразовать обратно в фактор и сохранить в определенном внешнем фрейме данных. Это исключает любые неиспользуемые уровни факторов без загрузки всех данных в память.
источник
Попробовал большинство примеров здесь, если не все, но ни один, кажется, не работает в моем случае. После долгого времени я пытался использовать as.character () для столбца factor, чтобы изменить его на col со строками, который, кажется, работает нормально.
Не уверен в проблемах с производительностью.
источник