1. Importar y Transformar variables
1 Abrir los datos
Lo primero de todo es importar tu base de datos a R. Para ello tienes que fijarte (1) en dónde está ubicada la base de datos (el path, p.ej. ‘Master/Encuestas/Datos’), para decirle a R qué archivo es exactamente, y (2) su formato (.xlsx de excel, .csv, .sav de spss, etc.) para saber qué función de lectura usar.
Según el formato del archivo tendrás que usar una función u otra, ya que cada una ha sido diseñada para leer un tipo de archivo específico:
Si tu archivo es .xlsx (excel), usarás del paquete readxl la función read_xlsx()
Si es .csv, readr::read_csv()
Si es .sav (spss) o .dta (stata) tienes las funciones en el paquete haven.
Sabiendo que tienes estos tres paquetes (readxl, readr y haven) puedes abrir casi cualquier archivo buscando cuál de ellos tiene la función específica.
Recuerda que dentro de cada función especificas el path!! es decir, el nombre del archivo.
Un ejemplo fake:
# archivo de spss en la carpeta 'micarpeta'
data <- haven::read_spss('micarpeta/data.sav')
# archivo ecel en la misma carpeta en la que estoy
data <- readxl::read_spss('data.xlsx')
# archivo csv en la carpeta datos de mis carpetas
data <- readr::read_csv('micarpeta/datos/data.csv')1.1 Entender los paths
Vale, pero ¿qué es eso de los paths?
Lo primero a tener claro, es que tu base de datos en tu carpeta no se llama solo ‘CIS_2022.sav’, sino, ‘C:/Users/Pepe/Master/Encuestas/Datos/CIS_2022.sav’. Por eso puedes tener archivos con el mismo nombre siempre y cuando estén en carpetas diferentes, sino, el ordenador no sabría diferenciar el archivo.
Una vez tenemos claro esto, lo segundo es entender que la sesión de RStudio en la que estamos trabajando no se abre en el vacío, ni en una dimensión paralela, sino desde una ubicación de tu ordenador.
¿Desde cuál? Con la función getwd() podemos saberlo:
getwd()## [1] "C:/Users/Romen/Archivos/Clases_particulares/Carla/Apuntes"
Si por ejemplo pones un script de R en tu Escritorio y haces doble clik y se abre una nueva sesión, al hacer getwd() obtendría algo tipo
## C:/Users/Carla/Desktop
Pero si lo tienes en tu carpeta de master y lo abres desde ahi, verías algo como:
## C:/Users/Carla/Master/Encuestas
Esto es importante porque según cual sea la dirección de nuestra sesión de R, podemos usar un path u otro para abrir nuestra base de datos.
Es decir, si mi sesión de R está en esta dirección:
## C:/Users/Carla/Master/Encuestas
Y los datos están justamente en la carpeta de Encuestas, bastaría con hacer:
read.csv('cis.csv')Es decir, R buscará en la carpeta de Encuestas así que no hace falta especificarla.
Si están en una carpeta llamada ‘datos’ dentro de ‘Encuestas’, entonces:
read.csv('datos/cis.csv')Y si están en ‘CIS’ que está en ‘datos’ que está en ‘Definitivo’ que está en ‘Encuestas’:
read.csv('Definitivo/datos/CIS/cis.csv')Pero, y si no está en la carpeta de Encuestas que es donde tenemos la sesión, sino en una anterior, pues damos ‘2 pasos’ pa atrás:
read.csv('../cis.csv')Y si está en un paso antes, pero dentro de otra carpeta llamada ‘clases’? Pues vamos pa atrás y luego pa ‘clases’
read.csv('../clases/cis.csv')Y si está no una, sino dos carpetas antes de Encuestas? Pues dos veces pa atrás.
read.csv('../../cis.csv')Esto puede ser infinito.
Para terminar, ¿podrías olvidarte de todo esto y usar siempre el path entero? Es decir:
read.csv('C:/Users/Carla/Master/Encuestas/Tarea - 1/Ejercicio 18/Definitivo/Ahora si definitivo/datos/CIS/cis.csv')Sí podrías, pero si haces algún cambio de nombre en una de tus carpetas te dará error. Y si estás trabajando colaborativamente y compartes tu script la persona tendrá que estar cambiando el path (vaya tostón). Así que mejor entender esto de los paths y todos más felices :)
2 Inspeccionar tus datos
Recuerda que en R los datos los puedes tener como dataframe o como tibble (este segundo es casi lo mismo salvo por algunas pequeñas diferencias). Mi recomendación es trabajar con tibbles.
Para saber de qué clase es el objeto:
# mtcars es una base de datos que viene por defecto con R
class(mtcars)## [1] "data.frame"
Ves que el resultado te dice que es un data.frame. Pero puedes transformarlo a tibble así:
library(dplyr)
mtcars_tibble <- as_tibble(mtcars)
# hemos creado un nuevo objeto llamado mtcars_tibble, que tiene la misma
# información que mtcars, pero que es un tibble en vez de un data.frameY mira cómo ahora sí es un tibble:
class(mtcars_tibble)## [1] "tbl_df" "tbl" "data.frame"
Una vez hecho esto, es importantísimo hechar un vistazo a tus datos. Para ello simplemente ejecutamos el objeto en consola (o con ctrl+Enter desde el script):
mtcars_tibble## # A tibble: 32 x 11
## mpg cyl disp hp drat wt qsec vs am gear carb
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 21 6 160 110 3.9 2.62 16.5 0 1 4 4
## 2 21 6 160 110 3.9 2.88 17.0 0 1 4 4
## 3 22.8 4 108 93 3.85 2.32 18.6 1 1 4 1
## 4 21.4 6 258 110 3.08 3.22 19.4 1 0 3 1
## 5 18.7 8 360 175 3.15 3.44 17.0 0 0 3 2
## 6 18.1 6 225 105 2.76 3.46 20.2 1 0 3 1
## 7 14.3 8 360 245 3.21 3.57 15.8 0 0 3 4
## 8 24.4 4 147. 62 3.69 3.19 20 1 0 4 2
## 9 22.8 4 141. 95 3.92 3.15 22.9 1 0 4 2
## 10 19.2 6 168. 123 3.92 3.44 18.3 1 0 4 4
## # ... with 22 more rows
Como es un tibble, nos muestra las primeras diez filas. También es útil utilizar a continuacuón la función glimpse() para ver el tipo de variables que tenemos de forma más compacta:
glimpse(mtcars_tibble)## Rows: 32
## Columns: 11
## $ mpg <dbl> 21.0, 21.0, 22.8, 21.4, 18.7, 18.1, 14.3, 24.4, 22.8, 19.2, 17.8,~
## $ cyl <dbl> 6, 6, 4, 6, 8, 6, 8, 4, 4, 6, 6, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 8,~
## $ disp <dbl> 160.0, 160.0, 108.0, 258.0, 360.0, 225.0, 360.0, 146.7, 140.8, 16~
## $ hp <dbl> 110, 110, 93, 110, 175, 105, 245, 62, 95, 123, 123, 180, 180, 180~
## $ drat <dbl> 3.90, 3.90, 3.85, 3.08, 3.15, 2.76, 3.21, 3.69, 3.92, 3.92, 3.92,~
## $ wt <dbl> 2.620, 2.875, 2.320, 3.215, 3.440, 3.460, 3.570, 3.190, 3.150, 3.~
## $ qsec <dbl> 16.46, 17.02, 18.61, 19.44, 17.02, 20.22, 15.84, 20.00, 22.90, 18~
## $ vs <dbl> 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,~
## $ am <dbl> 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,~
## $ gear <dbl> 4, 4, 4, 3, 3, 3, 3, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4, 4, 3, 3,~
## $ carb <dbl> 4, 4, 1, 1, 2, 1, 4, 2, 2, 4, 4, 3, 3, 3, 4, 4, 4, 1, 2, 1, 1, 2,~
Como puedes ver en este caso son todas numéricas (eso significa la etiqueta ‘dbl’, que proviene de double).
También es muy útil la función summary para tener un resumen de cada variable:
summary(mtcars_tibble)## mpg cyl disp hp
## Min. :10.40 Min. :4.000 Min. : 71.1 Min. : 52.0
## 1st Qu.:15.43 1st Qu.:4.000 1st Qu.:120.8 1st Qu.: 96.5
## Median :19.20 Median :6.000 Median :196.3 Median :123.0
## Mean :20.09 Mean :6.188 Mean :230.7 Mean :146.7
## 3rd Qu.:22.80 3rd Qu.:8.000 3rd Qu.:326.0 3rd Qu.:180.0
## Max. :33.90 Max. :8.000 Max. :472.0 Max. :335.0
## drat wt qsec vs
## Min. :2.760 Min. :1.513 Min. :14.50 Min. :0.0000
## 1st Qu.:3.080 1st Qu.:2.581 1st Qu.:16.89 1st Qu.:0.0000
## Median :3.695 Median :3.325 Median :17.71 Median :0.0000
## Mean :3.597 Mean :3.217 Mean :17.85 Mean :0.4375
## 3rd Qu.:3.920 3rd Qu.:3.610 3rd Qu.:18.90 3rd Qu.:1.0000
## Max. :4.930 Max. :5.424 Max. :22.90 Max. :1.0000
## am gear carb
## Min. :0.0000 Min. :3.000 Min. :1.000
## 1st Qu.:0.0000 1st Qu.:3.000 1st Qu.:2.000
## Median :0.0000 Median :4.000 Median :2.000
## Mean :0.4062 Mean :3.688 Mean :2.812
## 3rd Qu.:1.0000 3rd Qu.:4.000 3rd Qu.:4.000
## Max. :1.0000 Max. :5.000 Max. :8.000
3 Transformar las variables
Para aprender a limpiar variables vamos a usar los datos del CIS de enero de 2022. Como es un archivi .sav usamos la función de haven y guardamos los datos en un objeto que he llamado df_raw.
Nos vamos a quedar con 3 variables (para ello usamos la función select) que usaremos como ejemplo.
library(dplyr)
cis_raw <- haven::read_spss('cis2022-01.SAV')
# leemos la base de datos cis2022-01.sav con read_spss porque es .sav y
# guardados los datos en un objeto al que hemos llamado cis_rawclass(cis_raw) # como puedes ver es un tibble## [1] "tbl_df" "tbl" "data.frame"
Con la función dim vemos el número de filas y columnas que tiene.
dim(cis_raw)## [1] 3777 292
Vamos a crear un nuevo tibble llamado df que contenga 3 variables y aprovechamos para renombrarlas en el mismo select:
df <- cis_raw %>%
select('hombre'=SEXO, 'edad'=EDAD, 'ideol'=ESCIDEOL)
df## # A tibble: 3,777 x 3
## hombre edad ideol
## <dbl+lbl> <dbl+lbl> <dbl+lbl>
## 1 2 [Mujer] 79 99 [N.C.]
## 2 1 [Hombre] 56 99 [N.C.]
## 3 1 [Hombre] 65 5 [5]
## 4 1 [Hombre] 72 1 [1 Izquierda]
## 5 1 [Hombre] 38 5 [5]
## 6 1 [Hombre] 35 7 [7]
## 7 1 [Hombre] 42 5 [5]
## 8 1 [Hombre] 28 4 [4]
## 9 1 [Hombre] 32 3 [3]
## 10 1 [Hombre] 60 5 [5]
## # ... with 3,767 more rows
Si echamos un vistazo vemos que las 3 están codificadas como numéricas (dbl). Lo de ‘lbl’ es la etiqueta entre corchetes que le añade el CIS, yo siempre se las quito para que no me genere confusión.
glimpse(df)## Rows: 3,777
## Columns: 3
## $ hombre <dbl+lbl> 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 1, 1, 2,~
## $ edad <dbl+lbl> 79, 56, 65, 72, 38, 35, 42, 28, 32, 60, 67, 25, 63, 56, 42,~
## $ ideol <dbl+lbl> 99, 99, 5, 1, 5, 7, 5, 4, 3, 5, 5, 7, 2, 3, 3,~
3.1 Enviar valores a NA
Lo primero que vamos a aprender es a pasar valores a NA con la función ifelse. Pero, lo haremos en el torno tidyverse aprovechando la función mutate que nos permite crear nuevas columnas O (y aqui lo clave) sobreescribir las que ya existen.
¿Por qué pasamos valores a NA? Muy sencillo: porque son valores que no existen!! Dicho de otras palabras, si una persona no me responde una pregunta, esa celda debería estar vacía, porque la persona no ha dicho nada. Sin embargom, por ejemplo el CIS, opto por poner 98 o 99 habitualmente. Si tú por ejemplo vas a calcular la media de ideología de España y no pasas ese 98 y 99 a NA, te saldrá una media de 48, ¿qué significa eso? A saber. Por eso es importantísimo enviar a NA los valores que ‘no existen’. Y ¿cómo sabemos cuáles son? Mirando el Codebook (donde la institución explica qué significa cada variable y sus valores).
Como ejemplo, vamos a centrarnos en la variable ideología. Con un table() podemos ver qué categorías tiene y cuántas veces aparece cada categoría.
table(df$ideol)##
## 1 2 3 4 5 6 7 8 9 10 98 99
## 377 193 471 398 909 441 280 188 55 150 136 179
Como ya hemos mirado el Codebook del CIS, sabemos que tenemos que enviar a NA el 98 y 99. Para ello haremos:
Indicamos el nombre de nuestro dataframe (df) y añadimos el pipe ( %>% ) ya que vamos a aplicar una nueva operación
Utilizamos el mutate para sobreescribir la variable ideología. Antes del = va el nombre de la variable, si le damos un nombre que no está aún en los datos creará una nueva columna, si ponemos un nombre que ya existe la sobreescribirá. Hacemos lo segundo porque queremos transformar la variable.
Usamos la función ifelse(), en primer lugar le damos una condición (los valores de ideología mayores que 10). El segundo valor (después de la coma) que escribimos es NA, es decir, cuando un valor de ideología sea superior a 10 lo transformarmos a NA; y cuando no, lo dejamos como está (por eso ponemos al final ‘ideol’, el propio nombre de la variable).
df %>%
mutate( ideol = ifelse( ideol > 10, NA, ideol ) )## # A tibble: 3,777 x 3
## hombre edad ideol
## <dbl+lbl> <dbl+lbl> <dbl>
## 1 2 [Mujer] 79 NA
## 2 1 [Hombre] 56 NA
## 3 1 [Hombre] 65 5
## 4 1 [Hombre] 72 1
## 5 1 [Hombre] 38 5
## 6 1 [Hombre] 35 7
## 7 1 [Hombre] 42 5
## 8 1 [Hombre] 28 4
## 9 1 [Hombre] 32 3
## 10 1 [Hombre] 60 5
## # ... with 3,767 more rows
Si haces esto simplemente estarías ejecutando código pero no guardándolo!!! Para guardarlo recuerda siempre usar (<-), es decir:
df <- df %>%
mutate( ideol = ifelse( ideol > 10, NA, ideol ) )Así sobreescribimos el tibble df con nuestro cambio. Si ahora haces un table() para comprobar que se haya hecho bien, verás que ya no salen las etiquetas de 98 y 99, eso es porque ahora son NAs.
table(df$ideol)##
## 1 2 3 4 5 6 7 8 9 10
## 377 193 471 398 909 441 280 188 55 150
Para saber si una variable tiene NAs usamos summary:
summary(df$ideol)## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## 1.000 3.000 5.000 4.742 6.000 10.000 315
Nota: las condiciones que pones al principio de ifelse pueden ser mayor que (>), menor que(<), mayor o igual que (>=), menor o igual que (<=), igual ( == ) o distinto a (!=). Esto te da un gran flexibilidad.
Un ejemplo más, imagina que quieres convertir a NA no solo los numeros mayores que 10 sino también los menores o igual a 2. Esto lo podrías hacer con un solo ifelse pero te pongo el ejemplo de usar 2 para que veas como dentro de un mutate puedes ir haciendo varias cosas seguidas.
df %>%
mutate(
# convertimos los mayores de 10 a NA
ideol = ifelse( ideol > 10, NA, ideol ),
# y ahora los menores o igual a 2
ideol = ifelse( ideol <= 2, NA, ideol )
)
# como puedes ver no uso df <- , es decir, que no estoy guardando
# esta operación, solo ejecutando para que la veasPor último, también puedes mandar a NA etiquetas de una variable de tipo carácter o factor. Imagina este ejemplo hipotético donde la variable colores tuviera las categorías de ‘rojo’,‘verde’ y ‘no sabe’, podrías hacer:
data <- data %>%
mutate( color = ifelse(color=='no sabe', NA, color) )3.2 Conversiones básicas
Ten siempre presente las funciones:
as.numeric()
as.factor()
as.character()
porque te permiten transformar de forma sencilla cuando no tienes que dar condiciones ni especificar nada. Dicho de otra forma, no tienes que cambiar ningún valor, simplemente pasar de un tipo (carácter por ejemplo) a otro (por ejemplo a numérica).
Imagina este ejemplo de que importas unos datos, tienes la columna con la variable edad y ésta viene como carácter (como texto).
data_fake <- tibble(edad = c('15','25','18','25'))
data_fake## # A tibble: 4 x 1
## edad
## <chr>
## 1 15
## 2 25
## 3 18
## 4 25
Como ves es un carácter, pero puedes transformarla rápidamente a numérica con as.numeric():
data_fake <- data_fake %>%
mutate( edad = as.numeric(edad) )
data_fake## # A tibble: 4 x 1
## edad
## <dbl>
## 1 15
## 2 25
## 3 18
## 4 25
Las otras dos funciones siguen la misma lógica. Imagina que por alguna razón quisiéramos que ideología fuese carácter, pero sin hacer ningún cambio, bastaría con hacer:
data_fake %>%
mutate( ideol = as.character(ideol) )3.3 Convertir a factor
Cuando queremos convertir a factor una variable pero tenemos que cambiar algunos de sus valores, utilizamos la función factor().
Usando como ejemplo la variable hombre del CIS, vemos que tiene dos etiquetas (1 y 2) y sabemos que 1 corresponde a hombres.
table(df$hombre)##
## 1 2
## 1925 1852
Con la función factor, en levels ponemos las etiquetas que tiene la variable, y en labels los nuevos valores. Así ya queda transformada y convertida a factor.
df <- df %>%
mutate( hombre = factor( hombre,
levels = c('1','2'),
labels = c('Hombre','Mujer')) )
# haciendo df <- df estamos sobreescribiendo el tibble,
# es decir, creando un nuevo con la variable hombre como factor
# con las nuevas etiquetasImagina que tu variables es el voto a los partidos, tienes 7 partidos pero solo quieres quedarte con 2 y mandar el resto a la etiqueta ‘Otros’. También lo puedes hacer con factor:
# esto es un ejemplo hipotético
data %>%
mutate( voto = factor( voto,
levels = c('PP','PSOE','UP','MP','Cs','Vox','ERC'),
labels = c('PP','PSOE','Otros','Otros','Otros',
'Otros','Otros')) )3.4 Crear una dummy
Muchas veces tenemos que trabajar con dummys, es decir, variables que solo toman dos valores (1 o 0). En R hay una forma muy fácil de hacerla que es usando la función as.numeric() pero dándole una condición dentro. Imagina que queremos crear dos dummys, una que nos indique si la persona tiene 60 o más años y otra que nos diga si es de centro su ideología.
Las añadiremos como nuevas columnas de nuestro tibble:
df <- df %>%
mutate(
# creamos una nueva variable dummy llamada mayor_de_60
mayor_de_60 = as.numeric( edad >= 60 ),
# y otra para los de centro
es_de_centro = as.numeric( ideol == 5 )
)df## # A tibble: 3,777 x 5
## hombre edad ideol mayor_de_60 es_de_centro
## <fct> <dbl+lbl> <dbl> <dbl> <dbl>
## 1 Mujer 79 NA 1 NA
## 2 Hombre 56 NA 0 NA
## 3 Hombre 65 5 1 1
## 4 Hombre 72 1 1 0
## 5 Hombre 38 5 0 1
## 6 Hombre 35 7 0 0
## 7 Hombre 42 5 0 1
## 8 Hombre 28 4 0 0
## 9 Hombre 32 3 0 0
## 10 Hombre 60 5 1 1
## # ... with 3,767 more rows
Si hacemos un table de cada variable, vemos que ahora tenemos dos dummys que valen 1 cuando la persona tiene 60 o más años por un lado, y en otra que vale 1 cuando su ideología es el 5.
table(df$mayor_de_60)##
## 0 1
## 2534 1243
table(df$es_de_centro)##
## 0 1
## 2553 909
3.5 De numérica a factor
En ocasiones tenemos una variable numérica que queremos trocearla, es decir, convertir a categórica. Por ejemplo, en vez de usar la edad como numérica queremos diferenciarla en tres etiquetas: jóvenes, puretas y viejos.
Con la función cut() podemos hacer esto muy rápido. Vamos a crear una variable nueva en nuestro tibble que sea edad_factor.
A la función cut le indicamos en el parámetros ‘breaks’ los cortes que queremos hacer, en este caso le estamos diciendo que el primer grupo va entre -Inf (es decir, el valor maaas pequeño de edad que hubiera) hasta los 30 (y el 30 incluido). El segundo grupo va de los 30 (no incluido el 30) hasta los 60 años (60 si incluido), y el último va de los 60 hasta Inf (es decir el valor maaas grande de edad que haya).
Luego en labels = c(), le damos las etiquetas que queramos.
df <- df %>%
mutate( edad_factor = cut( edad,
breaks = c(-Inf, 30, 60, Inf),
labels = c('Jóvenes (<=30', 'Puretas (30-60)','Viejos (+60)')) )Haciendo un table() podemos ver el resultado de nuestra nueva variable:
table(df$edad_factor)##
## Jóvenes (<=30 Puretas (30-60) Viejos (+60)
## 506 2112 1159
4 Ejercicio
0.Importa a R la base de datos ‘cis_ejercicio’, es una copia de la que he usado aquí (CIS Ene 2022) pero le he cambiado el formato, no es un .sav, así que tendrás que mirar que formato es y usar la función de lectura apropiada :).
1. A continuación, crea un nuevo tibble pero quedándote solo con las variables Comunidad Autónoma (CCAA), tamaño de municipio (TAMUNI) y valoración de pedro sánchez (LIDERESVALORA_1). Renómbralas a ccaa, tamuni y val_sanchez
Recuerda antes de transformar comprobar siempre los valores de las variables con un table()!!!!
2. Crea una nueva variable llamada Canarias a partir de CCAA. Recuerda primero comprobar que no haya algún valor que debas enviar a NAs. Pista: convertir a dummy.
3. Envía a NAs los valores de tamuni que correspondan si es que hay alguno. Luego usando factor() agrupa las categorías 1 y 2, 3 y 4, 5 y 6, y deja 7 sola. Pista: para ello dale diferentes nombres en el parámetro de labels.
4. Mira en el codebook qué valores de val_sanchez (LIDERESVALORA_1) deberían ser NAs, y transforma la variable. No crees una nueva, sino sobreescribe la que existe.
5. Ahora, a partir de la variable val_sanchez ‘limpia’, crea una nueva llamada aprueban_a_sanchez que valga 1 si la persona ha respondido 6 o más.