Capítulo 10 Factores

¿Qué nos puede quedar más allá de las listas? Hay una forma de guardar los datos muy particular en R, que nos permite diferenciar variables no por su contenido en sí sino por lo que representan: hablemos de factores

Los factores la manera que tiene R para definir variables categóricas, también llamadas cualitativas, variables que aunque puedan ser números, en realidad representa categorías (categoría 1, 2, 3…). Algunos ejemplos de variables categóricas o cualitativas son las siguientes:

  • Estado civil (soltero/casado/viudo)
  • Diagnóstico del paciente (sano/leve/grave/fallecido)
  • Religión (musulmán/católico/ateo/budista)
  • País (España/Francia/Argentina)
  • Notas (suspenso/aprobado/notable/sobresaliente)
  • Colores (rojo/azul/verde)
  • Código postal (28017/34001/18003/33009)

¿Qué diferencias observas entre ellas?

Si las observas, bien algunas de ellas tienen asignadas una jerarquía (orden), a pesar de ser variables cualitativas. Es el caso de notas y diagnóstico, y son variables que llamamos variables cualitativas ordinales. En otros casos, no se puede (ni se debería) establecer una jerarquía, como es el caso de estado civil, religión, país, colores o código postal, variables cualitativas nominales. Además esta última es especial ya que es una varibale CUALItativa aunque esté formada por números: el código postal, los DNI, las tarjetas sanitarias, son variables que permiten identificar registros, direcciones o inviduos, por lo que su naturaleza no es cuantitativa (no cuantifican ninguna cantidad) sino cualitativa.

Esas variables cualitativas en R se llaman factores. Internamente los factores se guardan como variable numéricas enteras (enumerando las categorías) pero se nos mostarán con el nombre asignada a dicha categoría. Para convertir una variable a factor basta con ejecutar la función factor(), que nos convierte cada valor diferente en una categoría (para ver valores diferentes de un vector, usar la función unique()).

datos <- c(1, 2, 3, 1, 2, 3, 2, 3, 3, 1)
unique(datos)
## [1] 1 2 3
datos
##  [1] 1 2 3 1 2 3 2 3 3 1
# Convertimos a factor
datos_factor <- factor(datos) 
datos_factor 
##  [1] 1 2 3 1 2 3 2 3 3 1
## Levels: 1 2 3

 

WARNING: un factor es una CATEGORÍA, no un número

Es importante entender que un factor es una CATEGORÍA, como rojo/blanco/negro, por lo que desde el momento en el que lo convertimos en factor, ya no podemos hacer operaciones aritméticas (no podemos sumar categorías, solo números).

datos + 1
##  [1] 2 3 4 2 3 4 3 4 4 2
datos_factor + 1
##  [1] NA NA NA NA NA NA NA NA NA NA

 

Como puedes observar, al tenerlo en factor, además de la variable en sí se nos muestra debajo los levels, los niveles permitidos de las categorías. Si no le indicamos que nombres queremos, nos convierte los valores a texto y lo toma como nombre de categoría. Con el argumento labels podemos configurarlo a nuestro gusto. Con la función levels podemos reasignarle nombres tras su generación.

datos_factor <-
  factor(datos, labels = paste("Categoría", sort(unique(datos)))) # damos nombre de categoría 1, 2, 3...
datos_factor 
##  [1] Categoría 1 Categoría 2 Categoría 3 Categoría 1 Categoría 2 Categoría 3
##  [7] Categoría 2 Categoría 3 Categoría 3 Categoría 1
## Levels: Categoría 1 Categoría 2 Categoría 3
# Renombramos si queremos
levels(datos_factor) <- c("C1", "C2", "C3")
datos_factor
##  [1] C1 C2 C3 C1 C2 C3 C2 C3 C3 C1
## Levels: C1 C2 C3

Aunque sirve también para variables numéricas, la función table() nos calcula las frecuencias de cada una de las categorías, las veces que se repiten en nuestro conjunto (es una forma eficiente de guardar categorías ya que solo se guardan los valores únicos y el número de veces que se repiten, así como su lugar).

table(datos_factor)
## datos_factor
## C1 C2 C3 
##  3  3  4

Una ventaja de los factores es que le podemos indicar que considere que las categorías son ordinales con el argumento ordered = TRUE.

notas <- c(7, 2, 10, 5, 7, 8, 10, 8, 2, 2, 5, 5, 5, 10) # notas de clase: tienen un orden
notas_factor <- factor(notas)
notas_factor[1] < notas_factor[2]
## [1] NA
notas_factor_ordenados <- factor(notas, ordered = TRUE)
notas_factor_ordenados
##  [1] 7  2  10 5  7  8  10 8  2  2  5  5  5  10
## Levels: 2 < 5 < 7 < 8 < 10

Las variables cualitativas ordinales pueden ser comparadas al tener un orden.

notas_factor_ordenados[1] < notas_factor_ordenados[2] # nos dice que la categoría 7 no es menor que la categoría 2
## [1] FALSE

Y con summary() además podemos obtener un resumen de nuestras categorías

summary(notas_factor_ordenados)
##  2  5  7  8 10 
##  3  4  2  2  3

Para convertir de factor a numérica (y poder operar aritméticamente con ellos), basta usar la función as.numeric().

notas_factor_ordenados + 1
##  [1] NA NA NA NA NA NA NA NA NA NA NA NA NA NA
as.numeric(notas_factor_ordenados) + 1
##  [1] 4 2 6 3 4 5 6 5 2 2 3 3 3 6
mean(as.numeric(notas_factor_ordenados))
## [1] 2.857143

También podemos convertir variables continuas (o discretas) a factores indicando los rangos de las categorías que queremos asignar con la función cut(). Por ejemplo, supongamos que tenemos notas numéricas de clase y queremos asignar una nota categórica. En el argumento breaks debemos indicarle los cortes que queremos en los datos, teniendo n+1 valores, siendo n el número de categorías. Con right = FALSE le vamos a indicar que los intervalos son abiertos por la derecha.

notas <- c(7.4, 1.1, 2.9, 10, 5.2, 7.7, 8.9, 10, 8.1, 2.6, 2.4, 5.5, 5, 5, 10, 6.3, 9.4) # notas de clase
notas_categoricas <- cut(notas, breaks = c(0, 5, 7, 9, 10, 10.1), labels = c("suspenso", "aprobado", "notable", "sobresaliente", "mh"), right = FALSE)
notas_categoricas
##  [1] notable       suspenso      suspenso      mh            aprobado     
##  [6] notable       notable       mh            notable       suspenso     
## [11] suspenso      aprobado      aprobado      aprobado      mh           
## [16] aprobado      sobresaliente
## Levels: suspenso aprobado notable sobresaliente mh

Además, la función cut() identifica los datos de tipo fecha, pudiendo hacer cortes por unidades temporales.

fechas <- as.Date(c("2021-04-10", "2021-03-10", "2021-01-01", "2020-01-15", "2020-09-10", "2020-09-15", "2020-07-08"))
fechas_cortes <- cut(fechas, breaks = "year")
levels(fechas_cortes) <- c("2020", "2021")
fechas_cortes
## [1] 2021 2021 2021 2020 2020 2020 2020
## Levels: 2020 2021

10.1 Consejos

CONSEJOS

 

Paquete forcats

En dicho paquete tienes muchas funcionalidades para trabajar con factores. Ver https://forcats.tidyverse.org/.

Paquete lubridate.

Imagen/gráfica 10.1: Paquete lubridate.

 

10.2 📝 Ejercicios

Ejercicio 1: define una variable de 5 elementos con los valores vector_char <- c("H", "H", "M", "H", "M", "M", "H"). Convierte la variable a factor, y renombra los niveles como "Hombre" y "Mujer".

  • Solución:
# Vector de caracteres
vector_char <- c("H", "H", "M", "H", "M", "M", "H")
vector_char
## [1] "H" "H" "M" "H" "M" "M" "H"
class(vector_char)
## [1] "character"
# Convertimos a factor
vector_factor <- factor(vector_char)
vector_factor
## [1] H H M H M M H
## Levels: H M
class(vector_factor)
## [1] "factor"
# Renombramos niveles
levels(vector_factor) <- c("Hombre", "Mujer")
vector_factor
## [1] Hombre Hombre Mujer  Hombre Mujer  Mujer  Hombre
## Levels: Hombre Mujer

 

Ejercicio 2: define un vector con nombres de algunos animales y convierte el vector a factor.

  • Solución:
# Ejemplo
animales_char <- c("perro", "gato", "pájaro", "perro", "loro", "gato", "perro", "león")
animales_char
## [1] "perro"  "gato"   "pájaro" "perro"  "loro"   "gato"   "perro"  "león"
class(animales_char)
## [1] "character"
# Convertimos a factor
animales_vector <- factor(animales_char)
animales_vector
## [1] perro  gato   pájaro perro  loro   gato   perro  león  
## Levels: gato león loro pájaro perro
class(animales_vector)
## [1] "factor"

 

Ejercicio 3: define un vector con las notas notas_char <- c("Suspenso", "Aprobado", "Notable", "Sobresaliente", "Matrícula") y conviértelo a factor. OJO: ¿es una variable cualitativa nominal u ordinal? Calcula el resumen de la variable.

  • Solución:
# Notas (es ordinal)
notas_char <- c("Aprobado", "Suspenso", "Sobresaliente", "Notable",
                "Matrícula", "Aprobado", "Aprobado", "Notable",
                "Suspenso", "Sobresaliente",
                "Matrícula", "Suspenso")
notas_char 
##  [1] "Aprobado"      "Suspenso"      "Sobresaliente" "Notable"      
##  [5] "Matrícula"     "Aprobado"      "Aprobado"      "Notable"      
##  [9] "Suspenso"      "Sobresaliente" "Matrícula"     "Suspenso"
# Convertimos a factor ORDENADO
notas_factor <-
  factor(notas_char, order = TRUE,
         levels =  c("Suspenso", "Aprobado", "Notable", 
                     "Sobresaliente", "Matrícula"))
notas_factor
##  [1] Aprobado      Suspenso      Sobresaliente Notable       Matrícula    
##  [6] Aprobado      Aprobado      Notable       Suspenso      Sobresaliente
## [11] Matrícula     Suspenso     
## Levels: Suspenso < Aprobado < Notable < Sobresaliente < Matrícula
# Resumen
summary(notas_factor)
##      Suspenso      Aprobado       Notable Sobresaliente     Matrícula 
##             3             3             2             2             2

 

Ejercicio 4: de la variable notas_char anterior compara el elemento segundo y el cuarto.

  • Solución:
notas_factor[2] < notas_factor[4]
## [1] TRUE
notas_factor[2] > notas_factor[4]
## [1] FALSE