Categorizar variables en R
La función cut
permite cortar datos en grupos y especificar ‘etiquetas de corte’, por lo que es muy útil para crear un factor a partir de una variable continua. En este tutorial aprenderás cómo usar la función cut
en R y, por lo tanto, cómo categorizar variables en R.
La función cut() para categorizar variables
En ocasiones resulta útil categorizar los valores de una variable continua en diferentes grupos. Para ese propósito puedes usar la función cut
de R. En el siguiente bloque de código mostramos la sintaxis de la función y la descripción simplificada de los argumentos.
cut(num_vector, # Vector de entrada (numérico)
breaks, # Número o vector con los cortes
labels = NULL, # Etiquetas para cada grupo
include.lowest = FALSE, # Si se incluye el valor más pequeño o no en el primer intervalo
right = TRUE, # Si el intervalo derecho está cerrado (y el izquierdo abierto) o viceversa
dig.lab = 3, # Número de dígitos de los grupos si labels = NULL
ordered_result = FALSE, # Si se debería ordenar el resultado (TRUE) del factor o no (FALSE)
…) # Argumentos adicionales
Para más información sobre la función base para categorizar variables en R escribe help(cut)
o ?cut
en la consola de R o RStudio.
El argumento breaks
El argumento breaks
permite cortar los datos en subgrupos y, por lo tanto, clasificarlos. Considera el siguiente vector:
x <- -5:5
Por un lado, puedes establecer el argumento breaks
como un número entero, creando tantos intervalos (niveles) como los especificados. Estos intervalos serán todos de la misma longitud.
cut(x, breaks = 2)
(-5.01,0] (-5.01,0] (-5.01,0] (-5.01,0] (-5.01,0]
(-5.01,0] (0,5.01] (0,5.01] (0,5.01] (0,5.01] (0,5.01]
Levels: (-5.01,0] (0,5.01]
Por otro lado, también puedes especificar los intervalos que prefieras.
cut(x, breaks = c(-6, 2, 5))
(-6,2] (-6,2] (-6,2] (-6,2] (-6,2] (-6,2] (-6,2] (-6,2] (2,5] (2,5]
(2,5]
Levels: (-6,2] (2,5]
Cabe destacar que si los intervalos tienen decimales, puedes modificar el número de decimales con el argumento dig.lab
y decidir si ordenar o no los resultados con el argumento ordered_result
.
El argumento labels
También puedes cambiar los niveles del factor con el argumento labels
.
x <- c(12, 1, 25, 12, 65, 2, 6, 17)
cut(x, breaks = c(0, 3, 12, 15, 20, 80),
labels = c("Primero", "Segundo", "Tercero", "Cuarto", "Quinto"))
# Equivalente a
c <- cut(x, breaks = c(0, 3, 12, 15, 20, 80))
levels(c) <- c("Primero", "Segundo", "Tercero", "Cuarto", "Quinto")
Segundo Primero Quinto Segundo Quinto Primero Segundo Cuarto
Levels: Primero Segundo Tercero Cuarto Quinto
Incluír el valor más pequeño
El argumento include.lowest
especifica si el lado izquierdo del primer intervalo es abierto o cerrado. Por defecto se establece en FALSE
(abierto).
x <- 15:25
cut(x, breaks = c(15, 20, 25), include.lowest = FALSE)
<NA> (15,20] (15,20] (15,20] (15,20]
(15,20] (20,25] (20,25] (20,25] (20,25] (20,25]
Levels: (15,20] (20,25]
En este caso, el valor más bajo (15), no se incluye en el intervalo (el intervalo izquierdo está abierto), por lo que el valor se clasifica como NA
, porque el número 15 no pertenece a ninguno de los intervalos. Sin embargo, si estableces include.lowest
como TRUE
se incluirá el valor, ya que se cerrará el lado izquierdo del primer intervalo.
cut(x, breaks = c(15, 20, 25), include.lowest = TRUE)
[15,20] [15,20] [15,20] [15,20] [15,20]
[15,20] (20,25] (20,25] (20,25] (20,25] (20,25]
Levels: [15,20] (20,25]
El argumento right
Considera el caso en el que que quieres clasificar algunos datos (\(x\)) en las siguientes categorías:
- Bajo, si \(x \in\) [0, 150).
- Medio, si \(x \in\) [150, 200).
- Alto, si \(x \in\) [200, $ $).
Por defecto, el argumento right
está establecido como TRUE
, por lo que los intervalos están abiertos a la izquierda y cerrados a la derecha (x, y].
x <- c(75, 150, 160, 151, 216, 149)
categorias <- cut(x, breaks = c(0, 150, 200, Inf),
labels = c("bajo", "medio", "alto"))
data.frame(x, categorias)
En este escenario, no todos los valores se clasifican bien.
x categorias
75 bajo
150 bajo # <-- Categorizado como bajo
160 medio
151 medio
216 alto
149 bajo
Sin embargo, si estableces right = FALSE
, los intervalos se cerrarán a la izquierda y se abrirán a la derecha.
categories <- cut(x, breaks = c(0, 150, 200, Inf),
labels = c("bajo", "medio", "alto"),
right = FALSE)
data.frame(x, categories)
Ahora los datos estarán categorizados correctamente:
x categorias
75 bajo
150 medio # <-- Categorizado como medio
160 medio
151 medio
216 alto
149 bajo
Cambiar los argumentos right
e include.lowest
puede provocar errores, por lo que recomendamos cambiar los valores del argumento breaks
en lugar de los demás.
Ejemplo: ¿Cómo categorizar grupos de edad en R?
Considera que deseas clasificar un vector numérico de edades en las siguientes categorías:
- 0-14: Niño.
- 15-24: Joven.
- 25-64: Adulto.
- 65 y más: Mayor.
edad <- c(0, 12, 89, 14, 25, 2, 65, 1, 16, 24, 67, 61, 64)
A primera vista, podrías pensar en poner lo siguiente, pero así surgirá un error.
cut(edad, breaks = c(14, 24, 64, Inf),
labels = c("Niño", "Joven", "Adulto", "Mayor"))
Error in cut.default(edad, breaks = c(14, 24, 64, Inf), labels = c(“Niño”,: lengths of ‘breaks’ and ‘labels’ differ
No obstante, al especificar 4 valores de corte y 4 etiquetas, teniendo en cuenta que los cortes definen intervalos, los intervalos que generas son tres (14-24, 24-64 y 64-Inf). En consecuencia, deberás agregar en este caso el valor más bajo para tener cuatro intervalos en lugar de tres:
cut(edad, breaks = c(0, 14, 24, 64, Inf),
labels = c("Niño", "Joven", "Adulto", "Mayor"))
NA Niño Mayor Niño Adulto Niño Mayor Niño Joven Joven
Mayor Adulto Adulto
Levels: Niño Joven Adulto Mayor
Sin embargo, la edad más baja (0) se clasificará como NA
, ya que el mínimo de los intervalos no se incluye por defecto. Puedes resolver esto cambiando el 0 de los cortes (por ejemplo, poniendo -0.01 en lugar de 0) o estableciendo el argumento include.lowest
como TRUE
.
cut(edad, breaks = c(-0.01, 14, 24, 64, Inf),
labels = c("Niño", "Joven", "Adulto", "Mayor"))
# Equivalente a:
cut(edad, breaks = c(0, 14, 24, 64, Inf),
labels = c("Niño", "Joven", "Adulto", "Mayor"),
include.lowest = TRUE)
Niño Niño Mayor Niño Adulto Niño Mayor Niño Joven Joven
Mayor Adulto Adulto
Levels: Niño Joven Adulto Mayor
Ejemplo: ¿Cómo categorizar notas de exámenes en R?
Revisaremos ahora otro ejemplo. Las notas de exámenes son variables continuas que se pueden clasificar como suspensas, si la nota es inferior a 5 puntos sobre 10 o aprobadas en otro caso. Generaremos un conjunto de datos muy sencillo para clasificar las calificaciones de los exámenes.
notas <- c(6.1, 5.3, 8.9, 5.0, 8.8, 1.9, 6.6, 7.2, 9.4, 4.9,
7.1, 3.9, 1.0, 9.3, 9.9, 5.9, 5.1, 8.4, 3.2, 10.0)
En este ejemplo podrías implementar la función como sigue:
notas_categorizadas <- cut(notas, breaks = c(0, 4.9, 10),
labels = c("suspenso", "aprobado"))
# Equivalente a:
# notas_categorizadas <- cut(notas, breaks = c(0, 5, 10.1),
# labels = c("suspenso", "aprobado"), right = FALSE)
# También puedes especificar los niveles de los factores con la función levels
# levels(notas_categorizadas) <- c("suspenso", "aprobado")
# Generamos un data frame
notas_finales <- data.frame(notas, notas_categorizadas)
head(notas_finales)
Ten en cuenta que en el método alternativo equivalente establecemos right = FALSE
, porque si fuese TRUE
un 5 sería un suspenso en lugar de un aprobado. Sin embargo, al establecer este argumento como FALSE
, el lado derecho del intervalo estará abierto, por lo que un 10 no entraría en ningún intervalo y esa es la razón por la que establecemos el tercer corte en 10.1 en lugar de 10. El resultado final es el siguiente:
notas notas_categorizadas
1 6.1 aprobado
2 5.3 aprobado
3 8.9 aprobado
4 5.0 aprobado
5 8.8 aprobado
6 1.9 suspenso