install.packages("paquete")
library(paquete)
Procesamiento, limpieza y manipulación de datos en R
Presentación
Objetivo de la práctica
El objetivo de esta guía práctica adicional es revisar algunos procedimientos básicos de la preparación de datos con R base, sirviendo como material complementario a lo apredendido en la sesión n° 3 del laboratorio.
Procesamiento de datos
1 Cargar librerías
En R se trabaja a partir de paquetes (packages). ¿Qué son? De forma resumida, los paquetes son un conjunto de funciones o herramientas que pueden ser usadas en R. Los directorios de R donde se almacenan los paquetes se denominan librerías. La lógica es instalar paquetes y luego cargar (o llamar) las librerías cada vez que es necesario usarlas.
Usualmente para cargar paquetes lo hacemos de la siguiente manera:
Pero en esta ocasión utilizaremos un paquete llamado pacman, que facilita y agiliza la lectura (instalación y carga) de los paquetes a utilizar en R. De esta forma lo instalamos 1 única vez así:
install.packages("pacman")
library(pacman)
Luego instalaremos y cargaremos los paquetes de R de la siguiente manera, volviendo más eficiente el procedimiento de carga de paquetes.
En este práctico utilizaremos seis paquetes
pacman
: este facilita y agiliza la lectura de los paquetes a utilizar en Rtidyverse
: colección de paquetes, de la cual utilizaremos dplyr y havendplyr
: nos permite seleccionar variables de un set de datoshaven
: cargar y exportar bases de datos en formatos .sav y .dtacar
: para recodificar/agrupar valores de variablesmagrittr
: para manipular datos con%>%
::p_load(tidyverse, # colección de paquetes para manipulación de datos
pacman# para manipular datos
dplyr, # para importar datos
haven, # para recodificar datos
car, # para manipular datos
magrittr)
options(scipen = 999) # para desactivar notacion cientifica
rm(list = ls()) # para limpiar el entorno de trabajo
Como se puede ver, antes de la función p_load hay un ::
, esto se refiere a que se “fuerza” que esa función provenga de ese paquete (en este caso del paquete pacman
).
2 Importar datos
En R es es posible importar y exportar datos que se encuentren en cualquier formato: ya sea .csv, .dta, .sav, .xlsx y, por supuesto, .rds y .RData. Sin embargo, para poder hacerlo lo primero es instalar y cargar las librerías que contienen las funciones necesarias para la importación de distintos tipos de archivos.
Pero, ¿dónde están mis datos? Como hemos mencionado, nuestros datos los dejaremos en la carpeta input/data
de nuestro proyecto. La base con la que trabajaremos en este práctico pueden encontrarla en el material docente en U-Cursos, o bien, en el siguiente enlace.
Luego de descargar la base de datos, asegurate de dejar el archivo .sav en la carpeta input/data
de tu proyecto. Nota: Los datos tendrán distinto nombre según su formato (.sav, .csv, .dta, etc.).
Una vez descargados los datos y cargado el paquete haven
, procedemos a importar nuestra base de datos. Para ello, en nuestro script, dejamos indicado que a partir de la lectura de los datos con read_sav()
, crearemos un objeto llamado elsoc_2022
. Fijate en el Enviroment, ya que si lo anterior se logra, el objeto aparecerá allí.
La estructura general para importar datos es la siguiente:
read_*("ruta_hacia_archivo/nombre_archivo.*")
<- read_sav("ELSOC W06 v1.0 SPSS.sav") # No funciona
elsoc_2022
<- read_sav("input/data/ELSOC W06 v1.0 SPSS.sav") # No funciona
elsoc_2022
<- read_sav("input/data/ELSOC_W06_v1.0_SPSS.sav") # Si funciona! elsoc_2022
2.1.1 Importar datos en otros formatos
No siempre nuestros datos vendrán en un único formato. Para ello, R cuenta con otras formas de leer distintos tipos de formatos. Puedes ver las principales en el siguiente enlace.
3 Explorar datos
Lo más probable es que no trabajemos con todos los datos que importamos, por lo que debemos seleccionar aquellas variables con las que trabajaremos para nuestro problema de investigación (cualquiera sea).
Pero, para ello primero debemos explorar nuestros datos, si no ¿cómo puedo saber qué seleccionar y qué no? En R, las funciones más comunes para explorar datos son:
View(elsoc_2022) # Ver datos
names(elsoc_2022) # Nombre de columnas
dim(elsoc_2022) # Dimensiones
str(elsoc_2022) # Estructura de los datos (las clases y categorias de repuesta)
Tenemos una base de datos con 1000 casos o filas y con 13 variables o columnas.
4 Limpiar datos
Para todos los subprocesos que involucra la “limpieza” de datos, tenemos al menos dos maneras. Por un lado, podemos usar las funciones de R base, es decir, que no requieren paquetes extras. Por el otro, podemos usar las funciones del paquete dplyr()
, que es una gramática o dialecto de manipulación de datos que proporciona un conjunto de coherente funciones o “verbos” básicos para programar.
En este práctico nos centraremos solo en cómo manipular datos con el lenguaje de R base
4.1 Seleccionar
Una vez tenemos claras cúales son las variables que nos interesan, las seleccionamos y almacenamos en una nueva base de datos. Esto debido que evitará confusiones y hará más eficiente nuestros analísis en términos de memoria.
En R base, el primer argumento dentro del bracket []
refiere a las filas y el segundo a las columnas.
1] elsoc_2022[ ,
# A tibble: 1,000 × 1
m0_sexo
<chr>
1 Hombre
2 Mujer
3 Hombre
4 Hombre
5 Mujer
6 Mujer
7 Mujer
8 Mujer
9 Mujer
10 Hombre
# … with 990 more rows
También podemos seleccionar más de una columna/variable utilizando funciones básicas de R. Por ejemplo, usando c()
c(1,2,4)] #aqui le decimos que queremos las columnas especificas 1 2 y 4 elsoc_2022[,
# A tibble: 1,000 × 3
m0_sexo m0_edad c25
<chr> <dbl> <dbl>
1 Hombre 38 1
2 Mujer 45 1
3 Hombre 42 3
4 Hombre 29 1
5 Mujer 53 2
6 Mujer 52 3
7 Mujer 50 2
8 Mujer 57 1
9 Mujer 47 1
10 Hombre 79 2
# … with 990 more rows
O bien, indicando desde qué columna hasta cuál quiero seleccionar.
1:4] # aqui le decimos que queremos desde la columna 1 a la 4 elsoc_2022[,
# A tibble: 1,000 × 4
m0_sexo m0_edad m36 c25
<chr> <dbl> <dbl> <dbl>
1 Hombre 38 1 1
2 Mujer 45 4 1
3 Hombre 42 4 3
4 Hombre 29 4 1
5 Mujer 53 5 2
6 Mujer 52 1 3
7 Mujer 50 4 2
8 Mujer 57 8 1
9 Mujer 47 4 1
10 Hombre 79 4 2
# … with 990 more rows
Y, obviamente, podemos utilizar el nombre de las variables.
c("m0_sexo", "m0_edad")] elsoc_2022[,
# A tibble: 1,000 × 2
m0_sexo m0_edad
<chr> <dbl>
1 Hombre 38
2 Mujer 45
3 Hombre 42
4 Hombre 29
5 Mujer 53
6 Mujer 52
7 Mujer 50
8 Mujer 57
9 Mujer 47
10 Hombre 79
# … with 990 more rows
Ahora, ¡apliquemos conocimientos! seleccionando y renombrando las variables de interés en un nueva base llamada proc_elsoc
.
En este ejemplo utilizaremos las siguientes variables:
- m0_sexo: sexo del entrevistado
- m0_edad: edad del entrevistado
- m13: ingreso mensual entrevistado
- c25: preferencia entre autoritarismo y democracia
- f05_01: justificación violencia hacia delincuentes
<- elsoc_2022[, c(2,1,8,4,7)] # seleccionamos
proc_elsoc
proc_elsoc
# A tibble: 1,000 × 5
m0_edad m0_sexo m13 c25 f05_01
<dbl> <chr> <dbl> <dbl> <dbl>
1 38 Hombre 4000000 1 NA
2 45 Mujer 2700000 1 3
3 42 Hombre 600000 3 NA
4 29 Hombre 1250000 1 1
5 53 Mujer 500000 2 3
6 52 Mujer NA 3 2
7 50 Mujer NA 2 5
8 57 Mujer 0 1 4
9 47 Mujer 600000 1 3
10 79 Hombre NA 2 1
# … with 990 more rows
colnames(proc_elsoc) <- c("edad", "sexo", "ingreso", "autor_democ", "jv_delincuentes") # renonbramos
proc_elsoc
# A tibble: 1,000 × 5
edad sexo ingreso autor_democ jv_delincuentes
<dbl> <chr> <dbl> <dbl> <dbl>
1 38 Hombre 4000000 1 NA
2 45 Mujer 2700000 1 3
3 42 Hombre 600000 3 NA
4 29 Hombre 1250000 1 1
5 53 Mujer 500000 2 3
6 52 Mujer NA 3 2
7 50 Mujer NA 2 5
8 57 Mujer 0 1 4
9 47 Mujer 600000 1 3
10 79 Hombre NA 2 1
# … with 990 more rows
Esta nueva base de datos sigue manteniendo los 1.000 casos/filas, pero ahora solo tiene 5 variables/columnas. ¿Qué pasa si solo quiero trabajar con un subconjunto de estos datos, por ejemplo, las mujeres mayores a 25 años? La respuesta es filtrar.
4.2 Filtrar
Tal y como regularmente no trabajamos con todas las variables de una base de datos, no siempre desearemos trabajar con todas las observaciones que tenemos en los datos. Habrá ocasiones (varias) en las que querremos trabajar con casos que cumplan ciertas condiciones; que sean de determinada edad, residencia, tiempo o que simplemente hayan respondido de determinada forma una pregunta.
Ahora, en vez de trabajar con columnas trabajaremos con las filas. Esto lo haremos especificando condiciones de las variables en el primer argumento de los brackets []
.
$autor_democ == 1, ] # indicamos que en nuestra base proc_elsoc, queremos que nos deje aquellos casos que cumplen con la condicion de que autor_democr sea 2 proc_elsoc[proc_elsoc
# A tibble: 552 × 5
edad sexo ingreso autor_democ jv_delincuentes
<dbl> <chr> <dbl> <dbl> <dbl>
1 38 Hombre 4000000 1 NA
2 45 Mujer 2700000 1 3
3 29 Hombre 1250000 1 1
4 57 Mujer 0 1 4
5 47 Mujer 600000 1 3
6 39 Hombre 1350000 1 4
7 61 Mujer NA 1 3
8 25 Hombre NA 1 2
9 42 Hombre 1100000 1 4
10 51 Hombre 800000 1 1
# … with 542 more rows
Para indicarle a R que nos filtre aquellos casos que cumplen con la condición de ser iguales a 1 (autor_democ == 1), usamos el operador ==
. ¿Y esto de dónde salió? recuerda que los operadores en R los vimos en la segunda sesión.
También podemos agregar muchas condiciones para filtrar nuestros datos. Solamente debemos agregarlo.
$autor_democ == 1 & proc_elsoc$edad >= 25, ] # aqui le indicamos que nos filtre por casos que son autoritarismo/democracia igual 2 (no confia) y mayores o iguales a 25 años proc_elsoc[proc_elsoc
# A tibble: 544 × 5
edad sexo ingreso autor_democ jv_delincuentes
<dbl> <chr> <dbl> <dbl> <dbl>
1 38 Hombre 4000000 1 NA
2 45 Mujer 2700000 1 3
3 29 Hombre 1250000 1 1
4 57 Mujer 0 1 4
5 47 Mujer 600000 1 3
6 39 Hombre 1350000 1 4
7 61 Mujer NA 1 3
8 25 Hombre NA 1 2
9 42 Hombre 1100000 1 4
10 51 Hombre 800000 1 1
# … with 534 more rows
Pero, ¿y si tengo variables tipo character
o factor
? Tanto en R base como con dplyr
podemos especificar condiciones y filtrar este tipo de datos usando las comillas " "
.
$sexo == "Mujer", ] proc_elsoc[proc_elsoc
# A tibble: 656 × 5
edad sexo ingreso autor_democ jv_delincuentes
<dbl> <chr> <dbl> <dbl> <dbl>
1 45 Mujer 2700000 1 3
2 53 Mujer 500000 2 3
3 52 Mujer NA 3 2
4 50 Mujer NA 2 5
5 57 Mujer 0 1 4
6 47 Mujer 600000 1 3
7 61 Mujer NA 1 3
8 78 Mujer NA 4 1
9 65 Mujer NA 1 1
10 69 Mujer NA 2 1
# … with 646 more rows
¡Apliquémos conocimientos! Filtremos nuestros datos quedándonos solo con aquellos casos o personas que tengan o sean mayores a 25 años de edad.
<- proc_elsoc[proc_elsoc$edad >= 25, ]
proc_elsoc
proc_elsoc
# A tibble: 980 × 5
edad sexo ingreso autor_democ jv_delincuentes
<dbl> <chr> <dbl> <dbl> <dbl>
1 38 Hombre 4000000 1 NA
2 45 Mujer 2700000 1 3
3 42 Hombre 600000 3 NA
4 29 Hombre 1250000 1 1
5 53 Mujer 500000 2 3
6 52 Mujer NA 3 2
7 50 Mujer NA 2 5
8 57 Mujer 0 1 4
9 47 Mujer 600000 1 3
10 79 Hombre NA 2 1
# … with 970 more rows
4.3 Recodificar
Una parte fundamental del procesamiento e integración de datos es la recodificación de variables. Esto implica que, a determinadas variables, le aplicaremos ciertos cambios de acuerdo a ciertas reglas y criterios establecidos con anterioridad, siempre cuidando la coherencia con nuestro objetivo de investigación.
Hay múltiples formas de recodificar en R, pero en este ejemplo trabajaremos con el comando recode()
del paquete car
.
Esta vez, recodificaremos las siguientes variables: sexo
, ingreso
, autor_democ
y jv_delincuentes
. Para esto, nos apoyaremos en el libro de códigos.
Recodifiquemos la variable sexo e ingresos:
$sexo <- car::recode(proc_elsoc$sexo,
proc_elsocrecodes = c("'Hombre' = 'Masculino'; 'Mujer' = 'Femenino'"))
$ingreso <- car::recode(proc_elsoc$ingreso,
proc_elsocrecodes = c("-888 = NA; -999 = NA"))
proc_elsoc
# A tibble: 980 × 5
edad sexo ingreso autor_democ jv_delincuentes
<dbl> <chr> <dbl> <dbl> <dbl>
1 38 Masculino 4000000 1 NA
2 45 Femenino 2700000 1 3
3 42 Masculino 600000 3 NA
4 29 Masculino 1250000 1 1
5 53 Femenino 500000 2 3
6 52 Femenino NA 3 2
7 50 Femenino NA 2 5
8 57 Femenino 0 1 4
9 47 Femenino 600000 1 3
10 79 Masculino NA 2 1
# … with 970 more rows
Ahora recodifiquemos las demás variables. Además de recodificar valores propiamente tal, con recode()
podemos indicarle, en la misma función, que convierta la variable a factor
y/o que le asigne niveles (ej. para variables ordinales).
$autor_democ <- car::recode(proc_elsoc$autor_democ,
proc_elsocrecodes = c("1 = 'La democracia es preferible a cualquier otra forma de gobierno';
2 = 'En algunas circunstancias, un gobierno autoritario puede ser preferible a uno democratico';
3 = 'A la gente como uno, nos da lo mismo un regimen democratico que uno autoritario';
4 = 'Ninguna';
-888 = NA;
-999 = NA"),
as.factor = TRUE) # convertir a factor
$jv_delincuentes <- car::recode(proc_elsoc$jv_delincuentes,
proc_elsocrecodes = c("1 = 'Nunca';
2 = 'Pocas veces';
3 = 'Algunas veces';
4 = 'Muchas veces';
5 = 'Siempre';
-888 = NA;
-999 = NA"),
as.factor = TRUE, # convertir a factor
levels = c("Nunca",
"Pocas veces",
"Algunas veces",
"Muchas veces",
"Siempre")) # ordenamos niveles
proc_elsoc
# A tibble: 980 × 5
edad sexo ingreso autor_democ jv_de…¹
<dbl> <chr> <dbl> <fct> <fct>
1 38 Masculino 4000000 La democracia es preferible a cualquier otra… <NA>
2 45 Femenino 2700000 La democracia es preferible a cualquier otra… Alguna…
3 42 Masculino 600000 A la gente como uno, nos da lo mismo un regi… <NA>
4 29 Masculino 1250000 La democracia es preferible a cualquier otra… Nunca
5 53 Femenino 500000 En algunas circunstancias, un gobierno autor… Alguna…
6 52 Femenino NA A la gente como uno, nos da lo mismo un regi… Pocas …
7 50 Femenino NA En algunas circunstancias, un gobierno autor… Siempre
8 57 Femenino 0 La democracia es preferible a cualquier otra… Muchas…
9 47 Femenino 600000 La democracia es preferible a cualquier otra… Alguna…
10 79 Masculino NA En algunas circunstancias, un gobierno autor… Nunca
# … with 970 more rows, and abbreviated variable name ¹jv_delincuentes
4.4 Tratamiento casos pérdidos
Comúnmente, los datos con los que trabajamos suelen tener valores pérdidos o nulos que en R se denominan como NA
. Estos valores no nos entregan información útil para nuestros análisis, y pueden generar problemas al momento de, por ejemplo, calcular medidas de tendencia central, u otros procedimientos estadísticos.
Hay diversas maneras de trabajar los valores nulos. Sin embargo, la más sencilla consiste en eliminar los valores nulos que se encuentran presentes en nuestros datos.
El primer paso es identificar valores nulos en el conjunto de datos en general, o en alguna variable en específico. Para ello, empleamos la función is.na()
.
is.na(proc_elsoc)
is.na(proc_elsoc$ingreso)
Pero esto es poco útil. Como opción, podemos sumar o contar la cantidad de valores pérdidos.
sum(is.na(proc_elsoc))
[1] 515
¿Y si no sabemos qué variables o columnas tienen casos pérdidos? Una forma es usar la función colSums()
.
colSums(is.na(proc_elsoc))
edad sexo ingreso autor_democ jv_delincuentes
0 0 435 13 67
Una vez identificamos los valores nulos, podemos proceder a removerlos de la base de datos. El comando na.omit()
eliminará todas las filas que presenten casos perdidos.
<- na.omit(proc_elsoc)
proc_elsoc
proc_elsoc
# A tibble: 496 × 5
edad sexo ingreso autor_democ jv_de…¹
<dbl> <chr> <dbl> <fct> <fct>
1 45 Femenino 2700000 La democracia es preferible a cualquier otra… Alguna…
2 29 Masculino 1250000 La democracia es preferible a cualquier otra… Nunca
3 53 Femenino 500000 En algunas circunstancias, un gobierno autor… Alguna…
4 57 Femenino 0 La democracia es preferible a cualquier otra… Muchas…
5 47 Femenino 600000 La democracia es preferible a cualquier otra… Alguna…
6 39 Masculino 1350000 La democracia es preferible a cualquier otra… Muchas…
7 42 Masculino 1100000 La democracia es preferible a cualquier otra… Muchas…
8 51 Masculino 800000 La democracia es preferible a cualquier otra… Nunca
9 38 Masculino 1600000 A la gente como uno, nos da lo mismo un regi… Alguna…
10 45 Femenino 500000 La democracia es preferible a cualquier otra… Nunca
# … with 486 more rows, and abbreviated variable name ¹jv_delincuentes
5 Transformar variables
Un último paso en el procesamiento de datos es la creación o derivación de nuevas variables a partir de los datos que ya tenemos. Esto es relevante no solo para procesar datos, sino porque permite generar variables que se alineen mucho mejor con nuestros objetivos de análisis.
En este ejemplo, transformaremos las variables edad
e ingresos
, y crearemos una nueva variable llamada año
de la encuesta y otra llamada ingreso_minimo
.
¡Veámos cómo se hace!
Generemos las nueva variable año:
$ano <- 2022
proc_elsoc
proc_elsoc
Generemos nuevas variables para edad
e ingresos
dejándolas como tramos con ifelse()
.
$tramo_edad <- ifelse(proc_elsoc$edad <= 29, "Jovenes", proc_elsoc$edad)
proc_elsoc$tramo_edad <- ifelse(proc_elsoc$edad >= 30 & proc_elsoc$edad <= 59, "Adultos", proc_elsoc$tramo_edad)
proc_elsoc$tramo_edad <- ifelse(proc_elsoc$edad >= 60, "Adultos mayores", proc_elsoc$tramo_edad)
proc_elsoc
$tramo_ingreso <- ifelse(proc_elsoc$ingreso <= 250000, "Tramo 1", proc_elsoc$ingreso)
proc_elsoc$tramo_ingreso <- ifelse(proc_elsoc$ingreso > 250000 & proc_elsoc$ingreso <= 500000, "Tramo 2", proc_elsoc$tramo_ingreso)
proc_elsoc$tramo_ingreso <- ifelse(proc_elsoc$ingreso > 500000 & proc_elsoc$ingreso <= 750000, "Tramo 3", proc_elsoc$tramo_ingreso)
proc_elsoc$tramo_ingreso <- ifelse(proc_elsoc$ingreso > 750000 & proc_elsoc$ingreso <= 1000000, "Tramo 4", proc_elsoc$tramo_ingreso)
proc_elsoc$tramo_ingreso <- ifelse(proc_elsoc$ingreso > 1000000, "Tramo 5", proc_elsoc$tramo_ingreso)
proc_elsoc
proc_elsoc
# A tibble: 496 × 7
edad sexo ingreso autor_democ jv_de…¹ tramo…² tramo…³
<dbl> <chr> <dbl> <fct> <fct> <chr> <chr>
1 45 Femenino 2700000 La democracia es preferible … Alguna… Adultos Tramo 5
2 29 Masculino 1250000 La democracia es preferible … Nunca Jovenes Tramo 5
3 53 Femenino 500000 En algunas circunstancias, u… Alguna… Adultos Tramo 2
4 57 Femenino 0 La democracia es preferible … Muchas… Adultos Tramo 1
5 47 Femenino 600000 La democracia es preferible … Alguna… Adultos Tramo 3
6 39 Masculino 1350000 La democracia es preferible … Muchas… Adultos Tramo 5
7 42 Masculino 1100000 La democracia es preferible … Muchas… Adultos Tramo 5
8 51 Masculino 800000 La democracia es preferible … Nunca Adultos Tramo 4
9 38 Masculino 1600000 A la gente como uno, nos da … Alguna… Adultos Tramo 5
10 45 Femenino 500000 La democracia es preferible … Nunca Adultos Tramo 2
# … with 486 more rows, and abbreviated variable names ¹jv_delincuentes,
# ²tramo_edad, ³tramo_ingreso
Ahora, generemos una nueva variable llamada ingreso_minimo
con la función ifelse()
.
$ingreso_minimo <- ifelse(proc_elsoc$ingreso < 410000, "debajo minimo", "sobre minimo")
proc_elsoc
c("ingreso", "ingreso_minimo")] #veamosla! proc_elsoc[,
# A tibble: 496 × 2
ingreso ingreso_minimo
<dbl> <chr>
1 2700000 sobre minimo
2 1250000 sobre minimo
3 500000 sobre minimo
4 0 debajo minimo
5 600000 sobre minimo
6 1350000 sobre minimo
7 1100000 sobre minimo
8 800000 sobre minimo
9 1600000 sobre minimo
10 500000 sobre minimo
# … with 486 more rows
7 Guardar y exportar datos procesados
¡Legamos al final! El último paso que nos queda es guardar y exportar nuestra base de datos procesada. Siguiendo el flujo de trabajo propuesto, guardaremos la base procesada en formato .Rdata y la alojaremos en la carpeta output
de nuestro proyecto.
Este último paso es bastante sencillo, solo debemos especificar la base que queremos guadar y su ruta:
saveRDS(proc_elsoc, file = "output/datos_proc.Rdata")