Factor en R

Introducción a R Estructuras de datos
Crea datos categóricos con la función factor en R

Los factores en R se utilizan para representar datos categóricos. Se puede pensar en ellos como vectores en los que cada elemento tiene una etiqueta asociada. Ten en cuenta que es preferible utilizar factores con etiquetas que vectores enteros para indicar categorías, ya que las etiquetas son autodescriptivas. En esta lección aprenderás todo sobre cómo crear un factor en R.

¿Qué es un factor en R?

Un factor en R es una estructura de datos utilizada para representar un vector como datos categóricos. El objeto factor toma un número acotado de diferentes valores llamados niveles. Los factores son muy útiles cuando se trabaja con columnas de caracteres de data frames, para crear gráficos de barras y crear resúmenes estadísticos de variables categóricas.

La función factor

La función factor permite crear factores en R. En el siguiente bloque se muestran los argumentos de la función con una descripción resumida.

factor(x = character(),         # Vector de entrada
       levels,                  # Valores únicos de x (opcional)
       labels = levels,         # Etiquetas para los niveles (opcional)
       exclude = NA,            # Valores a excluir de los niveles
       ordered = is.ordered(x), # Si los niveles de entrada están ordenados o no
       nmax = NA)               # Máximo número de niveles

Puedes obtener una descripción más detallada de la función y sus argumentos ejecutando ?factor o help(factor).

Convertir carácter en factor en R

Ahora revisaremos un ejemplo donde nuestro input es un vector de caracteres. Supón que tienes un vector que contiene los días de la semana en los que sucedió algún evento. Puedes convertir el vector de caracteres a factor utilizando la función factor.

dias <- c("Viernes", "Martes", "Jueves", "Lunes", "Miércoles", "Lunes",
          "Miércoles", "Lunes", "Lunes", "Miércoles", "Domingo", "Sábado")

# Niveles en orden alfabético
mi_factor <- factor(dias)
mi_factor
Viernes  Martes  Jueves  Lunes  Miércoles  Lunes  Miércoles
Lunes  Lunes  Miércoles  Domingo  Sábado   
Levels: Domingo Jueves Lunes Martes Miércoles Sábado Viernes

Por defecto, al convertir un vector de caracteres en factor los niveles se ordenan alfabéticamente.

Si quieres conservar el orden de los niveles tal y como aparecen en los datos de entrada, especifica en el argumento levels lo siguiente:

factor(dias, levels = unique(dias))
Viernes  Martes  Jueves  Lunes  Miércoles Lunes
Miércoles Lunes  Lunes  Miércoles Domingo  Sábado   
Levels: Viernes Martes Jueves Lunes Miércoles Domingo Sábado

Cabe destacar que se pueden devolver y convertir los niveles de los factores en caracteres con la función levels.

levels(my_factor)
"Friday"  "Monday"  "Saturday"  "Sunday"  "Thursday"  "Tuesday"  "Wednesday"

Convertir variable numérica en factor

Supongamos ahora que has registrado la ciudad de nacimiento de seis personas con la siguiente codificación:

  • 1: Dublin.
  • 2: Londres,
  • 3: Sofia.
  • 4: Pontevedra.

Por lo tanto, tendrás datos almacenados en un vector numérico como los siguientes:

ciudad <- c(3, 2, 1, 4, 3, 2)

Ahora puedes llamar a la función factor para convertir y obtener los datos categorizados para su posterior análisis.

mi_factor <- factor(ciudad)
mi_factor

La salida tendrá la siguiente estructura:

3 2 1 4 3 2
Levels: 1 2 3 4

Cambiar las etiquetas de los niveles de un factor en R

Si el vector de entrada es numérico como sucedió en la sección anterior, la etiqueta correspondiente (la ciudad) no queda reflejada. Para resolver este problema, puedes almacenar los datos en un objeto de tipo factor utilizando la función factor e indicar las etiquetas correspondientes de los niveles en el argumento labels y así cambiar el nombre de los niveles del factor.

# Especificando las etiquetas en el orden correspondiente
factor_ciudades <- factor(ciudad, labels = c("Dublin", "Londres",
                                             "Sofia", "Pontevedra"))

# Imprimir el resultado
factor_ciudades
Sofia  Londres  Dublin  Pontevedra  Sofia  Londres    
Levels: Dublin Londres Sofia Pontevedra   # <- Dublin: 1, Londres: 2, Sofia: 3, Pontevedra: 4

En el bloque de código anterior puedes ver el resultado final. Como puedes observar, ahora los datos se clasifican usando las ciudades como etiquetas.

Diferencia entre los argumentos ‘levels’ y ‘labels’

Es común confundirse entre los argumentos labels y levels de la función factor en R. Considera el siguiente vector con un único grupo y crea un factor a partir de él con argumentos predeterminados:

genero <- c("femenino", "femenino", "femenino", "femenino")
factor(genero)
femenino  femenino  femenino  femenino
Levels: femenino

Ahora bien, por un lado, el argumento labels permite modificar los nombres de los niveles de factores. Por lo tanto, el argumento labels está relacionado con la salida. Ten en cuenta que la longitud del vector pasado al argumento debe ser de la misma longitud que la cantidad de grupos únicos del vector de entrada.

factor(genero, labels = c("f"))
f f f f
Levels: f

Por otro lado, el argumento levels está relacionado con la entrada. Este argumento permite especificar cómo están codificados los niveles que se quieren tratar. En consecuencia, este argumento permite agregar nuevos niveles al factor:

factor(genero, levels = c("masculino", "femenino"))
femenino  femenino  femenino  femenino
Levels: masculino femenino

Ten en cuenta que debes especificar al menos los mismos nombres de los grupos que forman el vector de entrada o la salida no será la esperada. Por ejemplo, si en el argumento levels escribimos “f” en lugar de “femenino” sucede lo que sigue:

factor(genero, levels = c("masculino", "f"))
<NA> <NA> <NA> <NA>
Levels: masculino f

Reordenar factores en R

Quizás te estés preguntando cómo cambiar el orden de los niveles (esto puede ser importante, por ejemplo, en algunas representaciones gráficas). El orden de los niveles de los factores se puede cambiar de varias maneras, descritas en las subsecciones siguientes.

Orden personalizado

En caso de que quieras crear un orden personalizado para los niveles, deberás crear un vector con el order que prefieres y pasarlo al argumento labels.

# Creando un vector con el orden deseado
orden <- c("Londres", "Sofia", "Dublin", "Pontevedra")

# Indica el orden en el argumento 'levels'
factor_ciudades <- factor(factor_ciudades, levels = orden)
factor_ciudades
Sofia Londres Dublin Pontevedra Sofia Londres   
Levels: Londres Sofia Dublin Pontevedra    # <- Ordenados como se especificó

También puedes ordenar alfabéticamente los niveles del factor utilizando la función sort:

# Orden alfabético
factor(ciudad, labels = sort(levels(factor_ciudades)))
Pontevedra  Londres  Dublin  Sofia  Pontevedra  Londres    
Levels: Dublin Londres Pontevedra Sofia    # <- Orden alfabético

La función reorder

La función reorder está diseñada para ordenar los niveles de un factor en función de una medida estadística de otra variable. Considera un data frame donde cada fila representa a un individuo, la columna ‘ciudad’ representa la ciudad donde nació y la columna ‘salario’ representa su salario anual real en miles de euros.

set.seed(1)
df <- data.frame(ciudad = factor_ciudades, salario = sample(20:50, 6))
df
      ciudad   salario
1      Sofia     28
2    Londres     31
3     Dublin     36
4 Pontevedra     45
5      Sofia     25
6    Londres     43

Puedes reordenar el factor en función del salario medio de las personas utilizando la función reorder de la siguiente manera:

reorder(df$ciudad, df$salario, mean)
Dublin   Londres   Sofia    Pontevedra 
 36.0     37.0     26.5       45.0 
Levels: Sofia Dublin Londres Pontevedra    # <- Ordenados de menor a mayor salario

Revertir el orden de los niveles

Recuerda que puedes usar la función levels para obtener los niveles de un factor. En este momento, los niveles del factor son los siguientes:

levels(factor_ciudades)
"Londres"  "Sofia"  "Dublin"  "Pontevedra"

Puedes revertir el orden de los niveles con la función rev:

factor(factor_ciudades, labels = rev(levels(factor_ciudades)))
Sofia  Dublin  Pontevedra  Londres  Sofia  Dublin    
Levels: Pontevedra Dublin Sofia Londres     # <- Orden revertido

La función relevel

Además, si quieres cambiar solo una observación y ponerla en primer lugar, puedes usar la función relevel. Por ejemplo, si quieres que ‘Londres’ sea el primer nivel y mantener el orden de los demás, puede usar:

# Poniendo el nivel 'Londres' de primero
factor_ciudades <- relevel(factor_ciudades, "Londres")
factor_ciudades
Sofia  Londres  Dublin  Pontevedra  Sofia  Londres    
Levels: Londres Dublin Sofia Pontevedra

En las siguientes secciones revisaremos cómo convertir factores a otros tipos de datos de la manera más eficiente posible.

Convertir factor en variable numérica

Si tienes un factor en R que quieres convertir a tipo numérico, la forma más eficiente se ilustra en el siguiente bloque de código, utilizando las funciones as.numeric y levels para indexar los niveles por el índice del factor correspondiente.

mis_datos <- c(0, 2, 0, 5, 1, 9, 9, 4)
mi_factor <- factor(mis_datos)

as.numeric(levels(mi_factor))[mi_factor]
0 2 0 5 1 9 9 4

Si quieres convertir el factor al vector original (con el mismo orden) nunca uses as.numeric(mi_factor), ya que devolverá un vector numérico diferente al deseado.

Convertir factor de R en string

Es posible que necesites convertir un factor en una cadena de caracteres. Para ello, puedes utilizar la función as.character.

mi_factor_2 <- factor(c("Junio", "Julio", "Enero", "Junio"))

as.character(mi_factor_2)
"Junio"  "Julio"  "Enero"  "Junio"

Nótese que si utilizas la función levels, la salida devolverá un vector de caracteres con las cadenas ordenadas alfabéticamente.

levels(mi_factor_2)
"Enero"  "Julio"  "Junio" 

Convertir un factor de R en clase date

Además, si necesitas convertir un objeto de tipo factor a fecha, puede usar la función as.Date, especificando en el argumento format el formato de fecha con el que estás trabajando.

factor_fechas <- factor(c("21/03/2020",
                           "22/03/2020",
                           "23/03/2020"))

as.Date(factor_fechas, format = "%d/%m/%Y")
"2020-03-21" "2020-03-22" "2020-03-23"