Mam ramkę danych zawierającą factor
. Kiedy tworzę podzbiór tej ramki danych za pomocą subset
lub innej funkcji indeksowania, tworzona jest nowa ramka danych. Jednak factor
zmienna zachowuje wszystkie swoje pierwotne poziomy, nawet jeśli / jeśli nie istnieją w nowej ramce danych.
Powoduje to problemy podczas wykonywania rysowania fasetowego lub korzystania z funkcji zależnych od poziomów czynników.
Jaki jest najbardziej zwięzły sposób usunięcia poziomów z czynnika w nowej ramce danych?
Oto przykład:
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)
preferowane jest rozwiązanie sugerowane przez Romana Luštrika i Tommy'ego O'Dell poniżej.Od wersji R 2.12 dostępna jest
droplevels()
funkcja.źródło
factor()
jest to, że nie trzeba modyfikować oryginalnej ramki danych ani tworzyć nowej trwałej ramki danych. Mogę owinąćdroplevels
podzbiór ramki danych i użyć jej jako argumentu danych funkcji kratowej, a grupy będą obsługiwane poprawnie.Jeśli nie chcesz tego zachowania, nie używaj czynników, zamiast tego użyj wektorów znaków. Myślę, że ma to większy sens niż załatanie później. Spróbuj wykonać następujące czynności przed załadowaniem danych za pomocą
read.table
lubread.csv
:Wadą jest to, że jesteś ograniczony do porządku alfabetycznego. (zmiana kolejności jest twoim przyjacielem dla działek)
źródło
Jest to znany problem, a jeden możliwy środek zapewnia
drop.levels()
w GData pakietu, gdzie staje się przykłademJest również
dropUnusedLevels
funkcja w pakiecie Hmisc . Działa to jednak tylko poprzez zmianę operatora podzbioru[
i nie ma tutaj zastosowania.W następstwie bezpośrednie podejście dla poszczególnych kolumn jest proste
as.factor(as.character(data))
:źródło
reorder
Parametrdrop.levels
funkcji warto wspomnieć: jeśli trzeba zachować oryginalną kolejność czynników, używać go zFALSE
wartością.Inny sposób robienia tego samego, ale z
dplyr
Edytować:
Działa również! Dzięki agenis
źródło
Dla kompletności, teraz jest również
fct_drop
wforcats
pakiecie http://forceats.tidyverse.org/reference/fct_drop.html .Różni
droplevels
się sposobem, w jaki zajmuje sięNA
:źródło
Oto inny sposób, który moim zdaniem jest równoważny
factor(..)
podejściu:źródło
`[.factor`
metoda, która madrop
argument, a ty opublikowałeś to w 2009 roku ...To jest wstrętne. Tak zazwyczaj to robię, aby uniknąć ładowania innych pakietów:
co daje ci:
Zauważ, że nowe poziomy zastąpią wszystko, co zajmuje ich indeks na starych poziomach (litery subdf $), więc coś takiego:
nie zadziała.
Nie jest to oczywiście idealne, gdy masz wiele poziomów, ale dla niektórych jest to szybkie i łatwe.
źródło
Patrząc na kod
droplevels
metod w źródle R, możesz zobaczyć, jak się zawijafactor
. Oznacza to, że można w zasadzie odtworzyć kolumnę zfactor
funkcją.Poniżej metody data.table, aby upuścić poziomy ze wszystkich kolumn czynników.
źródło
data.table
sposób byłby podobnyfor (j in names(DT)[sapply(DT, is.factor)]) set(DT, j = j, value = factor(DT[[j]]))
[.data.table
tylko razoto sposób na zrobienie tego
źródło
W tym celu napisałem funkcje narzędziowe. Teraz, gdy wiem o drop.levels gdata, wygląda całkiem podobnie. Oto one ( stąd ):
źródło
Bardzo interesujący wątek, szczególnie podoba mi się pomysł ponownego uwzględnienia podselekcji. Miałem wcześniej podobny problem i po prostu przekształciłem się w postać, a potem z powrotem w czynnik.
źródło
factor(as.chracter(...))
działa, ale tylko mniej wydajnie i zwięźle niżfactor(...)
. Wydaje się, że jest gorzej niż inne odpowiedzi.Niestety czynnik () wydaje się nie działać przy użyciu rxDataStep z RevoScaleR. Robię to w dwóch krokach: 1) Konwertuj na znak i przechowuj w tymczasowej zewnętrznej ramce danych (.xdf). 2) Konwertuj z powrotem na współczynnik i przechowuj w ostatecznej zewnętrznej ramce danych. Eliminuje to wszelkie nieużywane poziomy czynników, bez ładowania wszystkich danych do pamięci.
źródło
Próbowałem tutaj większości przykładów, jeśli nie wszystkie, ale wydaje się, że żaden nie działa w moim przypadku. Po dłuższym okresie zmagania próbowałem użyć as.character () w kolumnie czynnik, aby zmienić ją na kolumnę z ciągami, które wydają się działać dobrze.
Nie jestem pewien problemów z wydajnością.
źródło