studiodio questions programming org language instalar how frequently asked r factors r-faq

questions - r studiodio



Limpiar los niveles de factor(colapsando múltiples niveles/etiquetas) (7)

Como la pregunta se titula Limpieza de los niveles de los factores (colapso de múltiples niveles / etiquetas) , el paquete de los forcats debe mencionarse aquí, en aras de la exhaustividad. forcats aparecieron en CRAN en agosto de 2016.

Hay varias funciones de conveniencia disponibles para limpiar niveles de factor:

x <- c("Y", "Y", "Yes", "N", "No", "H") library(forcats)

Contraer los niveles de factor en grupos definidos manualmente

fct_collapse(x, Yes = c("Y", "Yes"), No = c("N", "No"), NULL = "H") #[1] Yes Yes Yes No No <NA> #Levels: No Yes

Cambiar los niveles de factor a mano

fct_recode(x, Yes = "Y", Yes = "Yes", No = "N", No = "No", NULL = "H") #[1] Yes Yes Yes No No <NA> #Levels: No Yes

Reetiquetar automáticamente los niveles de factor, colapsar según sea necesario

fun <- function(z) { z[z == "Y"] <- "Yes" z[z == "N"] <- "No" z[!(z %in% c("Yes", "No"))] <- NA z } fct_relabel(factor(x), fun) #[1] Yes Yes Yes No No <NA> #Levels: No Yes

Tenga en cuenta que fct_relabel() funciona con niveles de factor, por lo que espera un factor como primer argumento. Las otras dos funciones, fct_collapse() y fct_recode() , también aceptan un vector de caracteres que es una característica no documentada.

Reordenar los niveles de factor por primera aparición

El resultado esperado dado por el OP es

[1] Yes Yes Yes No No <NA> Levels: Yes No

Aquí los niveles se ordenan tal como aparecen en x que es diferente del valor predeterminado ( ?factor ?: Los niveles de un factor se clasifican por defecto ).

Para estar en línea con el resultado esperado, esto se puede lograr utilizando fct_inorder() antes de colapsar los niveles:

fct_collapse(fct_inorder(x), Yes = c("Y", "Yes"), No = c("N", "No"), NULL = "H") fct_recode(fct_inorder(x), Yes = "Y", Yes = "Yes", No = "N", No = "No", NULL = "H")

Ambos devuelven el resultado esperado con niveles en el mismo orden, ahora.

¿Cuál es la forma más efectiva (es decir, eficiente / apropiada) de limpiar un factor que contiene múltiples niveles que deben colapsarse? Es decir, cómo combinar dos o más niveles de factores en uno.

Aquí hay un ejemplo donde los dos niveles "Sí" e "Y" deben colapsarse a "Sí", y "No" y "N" colapsados ​​a "No":

## Given: x <- c("Y", "Y", "Yes", "N", "No", "H") # The ''H'' should be treated as NA ## expectedOutput [1] Yes Yes Yes No No <NA> Levels: Yes No # <~~ NOTICE ONLY **TWO** LEVELS

Una opción es, por supuesto, limpiar las cuerdas antes de la mano usando sub y amigos.

Otro método es permitir etiquetas duplicadas y luego colocarlas

## Duplicate levels ==> "Warning: deprecated" x.f <- factor(x, levels=c("Y", "Yes", "No", "N"), labels=c("Yes", "Yes", "No", "No")) ## the above line can be wrapped in either of the next two lines factor(x.f) droplevels(x.f)

Sin embargo, ¿hay una manera más efectiva ?

Si bien sé que los argumentos de levels y labels deben ser vectores, experimenté con listas y listas de nombres y vectores nombrados para ver qué sucede. De más está decir que ninguno de los siguientes me acercó más a mi objetivo.

factor(x, levels=list(c("Yes", "Y"), c("No", "N")), labels=c("Yes", "No")) factor(x, levels=c("Yes", "No"), labels=list(c("Yes", "Y"), c("No", "N"))) factor(x, levels=c("Y", "Yes", "No", "N"), labels=c(Y="Yes", Yes="Yes", No="No", N="No")) factor(x, levels=c("Y", "Yes", "No", "N"), labels=c(Yes="Y", Yes="Yes", No="No", No="N")) factor(x, levels=c("Yes", "No"), labels=c(Y="Yes", Yes="Yes", No="No", N="No"))


No sé cuál es tu caso de uso real, pero ¿qué strtrim tendría strtrim aquí?

factor( strtrim( x , 1 ) , levels = c("Y" , "N" ) , labels = c("Yes" , "No" ) ) #[1] Yes Yes Yes No No <NA> #Levels: Yes No


Otra forma es hacer una tabla que contenga el mapeo:

# stacking the list from Aaron''s answer fmap = stack(list(Yes = c("Y", "Yes"), No = c("N", "No"))) fmap$ind[ match(x, fmap$values) ] # [1] Yes Yes Yes No No <NA> # Levels: No Yes # or... library(data.table) setDT(fmap)[x, on=.(values), ind ] # [1] Yes Yes Yes No No <NA> # Levels: No Yes

Prefiero esta forma, ya que deja un objeto fácilmente inspeccionable que resume el mapa; y el código data.table se parece a cualquier otra unión en esa sintaxis.

Por supuesto, si no desea que un objeto como fmap resuma el cambio, puede ser un "trazador de líneas":

library(data.table) setDT(stack(list(Yes = c("Y", "Yes"), No = c("N", "No"))))[x, on=.(values), ind ] # [1] Yes Yes Yes No No <NA> # Levels: No Yes


Puede usar la función siguiente para combinar / contraer múltiples factores:

combofactor <- function(pattern_vector, replacement_vector, data) { levels <- levels(data) for (i in 1:length(pattern_vector)) levels[which(pattern_vector[i] == levels)] <- replacement_vector[i] levels(data) <- levels data }

Ejemplo:

Inicializar x

x <- factor(c(rep("Y",20),rep("N",20),rep("y",20), rep("yes",20),rep("Yes",20),rep("No",20)))

Verifica la estructura

str(x) # Factor w/ 6 levels "N","No","y","Y",..: 4 4 4 4 4 4 4 4 4 4 ...

Usa la función:

x_new <- combofactor(c("Y","N","y","yes"),c("Yes","No","Yes","Yes"),x)

Vuelva a verificar la estructura:

str(x_new) # Factor w/ 2 levels "No","Yes": 2 2 2 2 2 2 2 2 2 2 ...


Similar al enfoque de @ Aaron, pero un poco más simple sería:

x <- c("Y", "Y", "Yes", "N", "No", "H") x <- factor(x) # levels(x) # [1] "H" "N" "No" "Y" "Yes" # NB: the offending levels are 1, 2, & 4 levels(x)[c(1,2,4)] <- c(NA, "No", "Yes") x # [1] Yes Yes Yes No No <NA> # Levels: No Yes


Tal vez un vector con nombre como clave pueda ser de utilidad:

> factor(unname(c(Y = "Yes", Yes = "Yes", N = "No", No = "No", H = NA)[x])) [1] Yes Yes Yes No No <NA> Levels: No Yes

Esto se ve muy similar a tu último intento ... pero este funciona :-)


Utilice la función de levels y páselo por una lista con nombre, siendo los nombres los nombres deseados de los niveles y los elementos los nombres actuales que deben renombrarse.

x <- c("Y", "Y", "Yes", "N", "No", "H") x <- factor(x) levels(x) <- list(Yes=c("Y", "Yes"), No=c("N", "No")) x ## [1] Yes Yes Yes No No <NA> ## Levels: Yes No

Como se menciona en la documentación de levels ; también vea los ejemplos allí.

valor: para el método ''factor'', un vector de cadenas de caracteres con una longitud de al menos el número de niveles de ''x'', o una lista con nombre que especifica cómo cambiar el nombre de los niveles.

Esto también se puede hacer en una línea, como lo hace Marek aquí: https://.com/a/10432263/210673 ; los levels<- hechicería se explican aquí https://.com/a/10491881/210673 .

> `levels<-`(factor(x), list(Yes=c("Y", "Yes"), No=c("N", "No"))) [1] Yes Yes Yes No No <NA> Levels: Yes No