3.3 Factores

Los factores son tipos especiales de vectores, donde R evalúa los valores únicos de la secuencia y los define como categorías. Son muy útiles en programación dado que permiten graficar, por ejemplo, con un color diferenciado cada nivel de una variable categorica. Imagina que se requiere hacer un gráfico de dispersión de puntos para ver la relación entre dos variables, pero permitiendo que el color de los puntos refleje el grupo al que pertenece cada observación:

Ejemplo de uso de la variable Grupos (factor) empleada para colorear los puntos del gráfico de enfrentamiento de Pétalo y Sépalo.

Figura 3.4: Ejemplo de uso de la variable Grupos (factor) empleada para colorear los puntos del gráfico de enfrentamiento de Pétalo y Sépalo.

3.3.1 Crear un factor

Para crear un factor se utiliza la función factor(), y un vector dentro de ella. La función evaluará los valores únicos del vector y definirá los niveles del factor:

# Crear un vector de texto cualquiera 
vectorC <- c("A","B","A","A","A","A","B","A","C","C","B")

# Crear un vector de texto cualquiera
vectorN <- c(1,1,2,1,2,2,1,1,2,1,2,1,2,2,2,1)

# Crear factores en base a los vectores
factor(vectorC)
#  [1] A B A A A A B A C C B
# Levels: A B C
factor(vectorN)
#  [1] 1 1 2 1 2 2 1 1 2 1 2 1 2 2 2 1
# Levels: 1 2

3.3.2 Niveles de un factor

Cada factor muestra sus niveles (Levels) al final de la secuencia. Se puede conocer cuales son los niveles de un factor guardado en el ambiente, utilizando la función levels():

# Guardar el factor
F1 <- factor(vectorC)

# Revisar los niveles del factor
levels(F1)
# [1] "A" "B" "C"

3.3.3 Reordenar los niveles

El orden de los niveles es importante. Por defecto se ordenan los niveles de menor a mayor (si son números), o de la A a la Z (sin son texto). Para una regresión, para un gráfico, el orden afecta los resultados. En una regresión lineal, el primer nivel de un factor puede ser considerado como nivel base, y las interpretaciones se harán como factores de aumento o disminución de los otros niveles respecto al nivel base. En un gráfico, el orden de los colores, o las etiquetas de un eje, seguirán este orden.

Para cambiar el orden, las alternativas son variadas. Si solo se desea definir un nivel base, y el orden de los demás niveles no es importante, se usa relevel() con el segundo argumento especificando el nivel que será el nuevo nivel base.

# Especificando el primer nivel como "C" 
F1_cambiado <- relevel(F1, "C")
F1_cambiado
#  [1] A B A A A A B A C C B
# Levels: C A B

Si se necesita especificar un orden definido manualmente para todos los niveles, es mejor definirlo al momento de crear el factor, usando el argumento levels=:

# Crear un factor con niveles ordenados manualmente
F2 <- factor(vectorC, levels=c("B","C","A"))

# Revisar los niveles de F2
levels(F2)
# [1] "B" "C" "A"

3.3.4 Etiquetas de un factor

En algunas ocasionas existe la necesidad de cambiar el nombre de algún (o algunos) nivel(es), se puede usar un vector con los cambios deseados como contenido del argumento labels=. El orden de las etiquetas cambiadas debe seguir el mismo orden original de los niveles:

# Crear un factor con cambie de etiqueta
F3 <- factor(F1, labels=c("Absoluto", "B", "Cambio"))

# Revisar los niveles de F3
levels(F3)
# [1] "Absoluto" "B"        "Cambio"

# Revisando el contenido original (sin cambios) en F1
F1
#  [1] A B A A A A B A C C B
# Levels: A B C

# Revisar el contenido de F3
F3
#  [1] Absoluto B        Absoluto Absoluto Absoluto Absoluto B        Absoluto
#  [9] Cambio   Cambio   B       
# Levels: Absoluto B Cambio

Como fue evidente, al crear un factor se puede usar como insumo un vector, como vectorN, u otro factor previamente creado, como F1.

3.3.5 Valores perdidos en un factor

Los valores perdidos no forman parte de los niveles de un factor. Se muestran como contenido del conjunto de datos, pero no son considerados niveles.

conjunto1 <- c(1,2,1,1,NA,2,1,NA,3,2,1,3,2,3,3,NA)
fctConjunto1 <- factor(conjunto1)
fctConjunto1
#  [1] 1    2    1    1    <NA> 2    1    <NA> 3    2    1    3    2    3    3    <NA>
# Levels: 1 2 3

Por el contrario, si el investigador coloca deliberadamente los NA como texto, estos sí serán considerados como nivel:

conjunto2 <- c(1,2,1,1,"NA",2,1,"NA",3,2,1,3,2,3,3,"NA")
fctConjunto2 <- factor(conjunto2)
fctConjunto2
#  [1] 1  2  1  1  NA 2  1  NA 3  2  1  3  2  3  3  NA
# Levels: 1 2 3 NA

3.3.6 Indexación de factores

Indexar significa ubicar posiciones. Tal cual con un vector, en los factores cada elemento dentro del vector tiene una posición única. Para extraer el contenido de una posición única definida se utiliza igualmente el operador []. Utilicemos el objeto conjunto1 creado en la sección anterior:

fctConjunto2[3]
# [1] 1
# Levels: 1 2 3 NA

fctConjunto2[5]
# [1] NA
# Levels: 1 2 3 NA

El resto de reglas para indexar varios elementos a la vez, o indexar con vectores lógicos, son las mismas que para un vector:

# Indexar varios elementos a la vez
fctConjunto2[c(3,5,10)]
# [1] 1  NA 2 
# Levels: 1 2 3 NA

Indexar con operaciones relacionales puede ser engorroso. Debido a que los niveles del factor ya no son considerados números per se, sino que son categorías textuales, utiliza operaciones como mayor qué, menor qué y otras similares, produce resultados vacíos NA. Es imposible para R saber que Categoría 1 es menor igual que Categoría 2. No obstante, se pueden aún utiliza operaciones relacionales de igualdad:

# Con operación relacional de menor qué
# obtendremos un resultado erróneo
index <- fctConjunto2 < 3
# Warning in Ops.factor(fctConjunto2, 3): '<' not meaningful for factors
fctConjunto2[index]
#  [1] <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>
# Levels: 1 2 3 NA

# Con operación relacional de igualdad
index <- fctConjunto2 == 3
fctConjunto2[index]
# [1] 3 3 3 3
# Levels: 1 2 3 NA

# Utilizando el operador %in% podemos pedir 
# varias igualdades a la vez
index <- fctConjunto2 %in% c(1,2)
fctConjunto2[index]
# [1] 1 2 1 1 2 1 2 1 2
# Levels: 1 2 3 NA

Si se lidia con factores conteniendo NA (no su versión en texto NA), el indexar sin which() genera que se muestren los NA cuando no son requeridos. Utilicemos el objeto fctConjunto1:

index <- fctConjunto1 == 3
fctConjunto1[index]
# [1] <NA> <NA> 3    3    3    3    <NA>
# Levels: 1 2 3

Esto no ocurre al usar which() dentro de los []:

fctConjunto1[which(index)]
# [1] 3 3 3 3
# Levels: 1 2 3