Tengo un marco de datos que contiene a factor
. Cuando creo un subconjunto de este marco de datos usando subset
u otra función de indexación, se crea un nuevo marco de datos. Sin embargo, la factor
variable conserva todos sus niveles originales, incluso cuando / si no existen en el nuevo marco de datos.
Esto causa problemas al hacer trazados facetados o al usar funciones que dependen de niveles de factores.
¿Cuál es la forma más sucinta de eliminar niveles de un factor en el nuevo marco de datos?
Aquí hay un ejemplo:
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)
que es preferible la solución sugerida por Roman Luštrik y Tommy O'Dell a continuación.Desde R versión 2.12, hay una
droplevels()
función.fuente
factor()
es que no es necesario modificar el marco de datos original o crear un nuevo marco de datos persistente. Puedo ajustardroplevels
un marco de datos subconjunto y usarlo como argumento de datos para una función de red, y los grupos se manejarán correctamente.Si no desea este comportamiento, no use factores, use vectores de caracteres en su lugar. Creo que esto tiene más sentido que arreglar las cosas después. Pruebe lo siguiente antes de cargar sus datos con
read.table
oread.csv
:La desventaja es que está restringido al orden alfabético. (reordenar es tu amigo para las parcelas)
fuente
Es un problema conocido, y
drop.levels()
el paquete gdata proporciona un posible remedio donde su ejemplo se convierteTambién existe la
dropUnusedLevels
función en el paquete Hmisc . Sin embargo, solo funciona alterando el operador del subconjunto[
y no es aplicable aquí.Como corolario, un enfoque directo por columna es simple
as.factor(as.character(data))
:fuente
reorder
parámetro de ladrop.levels
función de la pena mencionar: si tiene que preservar el orden original de los factores, usarlo conFALSE
valor.Otra forma de hacer lo mismo pero con
dplyr
Editar:
También funciona! Gracias a agenis
fuente
En aras de la exhaustividad, ahora también hay
fct_drop
en elforcats
paquete http://forcats.tidyverse.org/reference/fct_drop.html .Se diferencia de
droplevels
la forma en que trataNA
:fuente
Aquí hay otra forma, que creo que es equivalente al
factor(..)
enfoque:fuente
`[.factor`
método que tiene undrop
argumento y que ha publicado esto en 2009 ...Esto es desagradable. Así es como lo hago generalmente, para evitar cargar otros paquetes:
que te lleva a:
Tenga en cuenta que los nuevos niveles reemplazarán todo lo que ocupe su índice en los niveles anteriores (subdf $ letras), así que algo como:
no funciona
Obviamente, esto no es ideal cuando tienes muchos niveles, pero para unos pocos, es rápido y fácil.
fuente
Mirando el código de
droplevels
métodos en la fuente R, puede ver que se ajusta parafactor
funcionar. Eso significa que básicamente puede recrear la columna con lafactor
función.Debajo de la forma data.table de eliminar niveles de todas las columnas de factores.
fuente
data.table
camino sería algo asífor (j in names(DT)[sapply(DT, is.factor)]) set(DT, j = j, value = factor(DT[[j]]))
[.data.table
solo una vezaquí hay una manera de hacerlo
fuente
Escribí funciones de utilidad para hacer esto. Ahora que sé sobre los niveles de caída de gdata, se ve bastante similar. Aquí están (desde aquí ):
fuente
Hilo muy interesante, me gustó especialmente la idea de factorizar nuevamente la subselección. Tuve el problema similar antes y simplemente me convertí en personaje y luego volví a factorizar.
fuente
factor(as.chracter(...))
funciona, pero de manera menos eficiente y sucinta quefactor(...)
. Parece estrictamente peor que las otras respuestas.Desafortunadamente, el factor () no parece funcionar cuando se usa rxDataStep de RevoScaleR. Lo hago en dos pasos: 1) Convertir a carácter y almacenar en un marco de datos externo temporal (.xdf). 2) Convertir de nuevo a factor y almacenar en un marco de datos externo definitivo. Esto elimina los niveles de factores no utilizados, sin cargar todos los datos en la memoria.
fuente
He probado la mayoría de los ejemplos aquí, si no todos, pero ninguno parece estar funcionando en mi caso. Después de luchar durante bastante tiempo, he intentado usar as.character () en la columna de factores para cambiarlo a una columna con cadenas que parece funcionar bien.
No estoy seguro de los problemas de rendimiento.
fuente