J'ai un bloc de données contenant un factor
. Lorsque je crée un sous-ensemble de cette trame de données à l'aide de subset
ou d'une autre fonction d'indexation, une nouvelle trame de données est créée. Cependant, lefactor
variable conserve tous ses niveaux d'origine, même si / s'ils n'existent pas dans la nouvelle trame de données.
Cela pose des problèmes lors du traçage à facettes ou de l'utilisation de fonctions qui dépendent des niveaux de facteur.
Quelle est la manière la plus succincte de supprimer des niveaux d'un facteur dans la nouvelle trame de données?
Voici un exemple:
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)
bloc de données en une liste, donc la solution suggérée par Roman Luštrik et Tommy O'Dell ci-dessous est préférable.Depuis R version 2.12, il existe une
droplevels()
fonction.la source
factor()
est qu'il n'est pas nécessaire de modifier la trame de données d'origine ou de créer une nouvelle trame de données persistante. Je peuxdroplevels
encapsuler une trame de données sous-définie et l'utiliser comme argument de données pour une fonction de réseau, et les groupes seront traités correctement.Si vous ne voulez pas de ce comportement, n'utilisez pas de facteurs, utilisez plutôt des vecteurs de caractères. Je pense que cela a plus de sens que de rafistoler les choses par la suite. Essayez ce qui suit avant de charger vos données avec
read.table
ouread.csv
:L'inconvénient est que vous êtes limité à l'ordre alphabétique. (réorganiser est votre ami pour les parcelles)
la source
Il s'agit d'un problème connu, et un remède possible est fourni par
drop.levels()
dans le package gdata où votre exemple devientIl y a aussi la
dropUnusedLevels
fonction dans le package Hmisc . Cependant, cela ne fonctionne qu'en modifiant l'opérateur de sous-ensemble[
et n'est pas applicable ici.En corollaire, une approche directe colonne par colonne est simple
as.factor(as.character(data))
:la source
reorder
paramètre de ladrop.levels
fonction mérite d'être mentionné: si vous devez conserver l'ordre d'origine de vos facteurs, utilisez-le avecFALSE
valeur.Une autre façon de faire la même chose mais avec
dplyr
Éditer:
Fonctionne également! Merci à agenis
la source
Par souci d'exhaustivité, il y a maintenant également
fct_drop
dans leforcats
package http://forcats.tidyverse.org/reference/fct_drop.html .Il diffère de
droplevels
la manière dont il traiteNA
:la source
Voici une autre façon, qui je crois est équivalente à l'
factor(..)
approche:la source
`[.factor`
méthode qui a undrop
argument et vous l'avez posté en 2009 ...C'est désagréable. Voici comment je le fais habituellement, pour éviter de charger d'autres packages:
ce qui vous donne:
Notez que les nouveaux niveaux remplaceront tout ce qui occupe leur index dans les anciens niveaux (lettres subdf $), donc quelque chose comme:
ne fonctionnera pas.
Ce n'est évidemment pas idéal lorsque vous avez beaucoup de niveaux, mais pour certains, c'est rapide et facile.
la source
En regardant le code des
droplevels
méthodes dans la source R, vous pouvez voir qu'ilfactor
fonctionne correctement . Cela signifie que vous pouvez recréer la colonne avec unefactor
fonction.Sous le moyen data.table pour supprimer les niveaux de toutes les colonnes de facteurs.
la source
data.table
chemin serait quelque chose commefor (j in names(DT)[sapply(DT, is.factor)]) set(DT, j = j, value = factor(DT[[j]]))
[.data.table
voici une façon de le faire
la source
J'ai écrit des fonctions utilitaires pour ce faire. Maintenant que je connais les drop.levels de gdata, cela semble assez similaire. Les voici (d' ici ):
la source
Fil très intéressant, j'ai particulièrement aimé l'idée de simplement factoriser à nouveau la sous-sélection. J'ai eu le même problème avant et je viens de convertir en personnage, puis de nouveau en facteur.
la source
factor(as.chracter(...))
fonctionne, mais juste moins efficacement et succinctement quefactor(...)
. Semble strictement pire que les autres réponses.Malheureusement, factor () ne semble pas fonctionner lors de l'utilisation de rxDataStep de RevoScaleR. Je le fais en deux étapes: 1) Convertir en caractère et stocker dans un cadre de données externe temporaire (.xdf). 2) Convertissez à nouveau en facteur et stockez dans une trame de données externe définitive. Cela élimine tous les niveaux de facteur inutilisés, sans charger toutes les données en mémoire.
la source
J'ai essayé la plupart des exemples ici, sinon tous, mais aucun ne semble fonctionner dans mon cas. Après avoir lutté pendant un certain temps, j'ai essayé d'utiliser as.character () sur la colonne factor pour le changer en un col avec des chaînes qui semble fonctionner très bien.
Pas sûr pour les problèmes de performances.
la source