Introducción
Las bases de datos provenientes de encuestas tienen algunos problemas que les son específicos y que requieren soluciones igualmente específicas. Aquí nos centramos en tres problemas:
- El manejo de etiquetas de variables y la creación de diccionarios de variables
- La combinación de pares de variables para facilitar la exploración bivariada
- Una solución a un problema de datos mal cargados: las variables separadas en múltiples columnas.
En los tres casos se utiliza extensamente la manipulación de listas y programación funcional. Son soluciones complejas a problemas (aparentemente) simples.
Conservar (y utilizar) los atributos de bases de datos de Stata o SPSS
Uno de los formatos de archivo en los que podemos encontrar bases de datos son los correspondientes a SPSS o Stata. Aunque no son formatos de archivo “nativos” de R
es muy fácil importarlo y convertirlos a un objeto de la clase data.frame.
Los archivos de SPSS o Stata permiten utilizar dos tipos de metadatos que no están disponibles directamente en R
: la Etiqueta de variable y las etiquetas de categorías y niveles para las variables categóricas.
Etiquetas de variables
En R
las columnas de un data.frame tienen un nombre. Como usamos R desde la consola y tenemos que escribir esos nombres en general buscamos que sean cortos y que no contengan espacios. El problema es que esos nombres son difíciles de recordar y, al momento de comunicar los resultados de un análisis, son casi imposibles de interpretar por un lector o lectora que no está familiarizado con esos nombres cortos. SPSS y Stata resuelven el problema agregando un segundo atributo a cada columna de una base de datos: las etiquetas. De este modo tenemos un nombre corto para llamar a una variable en el código y uno más largo y descriptivo para usarlo como etiqueta en los gráficos, tablas, etc. Es una ventaja grande y en R
no está disponible directamente. Esto no implica que no podamos aprovechar estos metadatos cuando están disponibles, aunque la solución requiera un poco de trabajo extra.
Cuando importamos un archivo .sav
o .dta
con alguna de las funciones de importación de la librería haven::
las etiquetas de cada variable también se importan y se registran en el atributo label
, asociado a cada columna del data.frame. Aunque son muy pocas las funciones o librerías que aprovechan este atributo de manera transparente para el usuario podemos extraer esta información para crear un diccionario de variables. Así podemos consultar las equivalencias entre pares de nombre-etiqueta.
Como label
es un atributo asociado a cada elemento de una lista no tiene el comportamiento vectorizado por defecto que esperamos de los vectores en R
. Para obtener un vector de etiquetas usamos la función map_chr()
de la librería purrr::
que se encarga de iterar la función attr
en cada elemento del data.frame y organizar el output como una vector. Ubicamos ese vector como columna del data.frame diccionario
. La otra columna la obtenemos con colnames()
, que por defecto nos regresa un vector y no requiere el uso explícito de un iterador.
library(haven)
library(tidyverse)
## Registered S3 methods overwritten by 'ggplot2':
## method from
## [.quosures rlang
## c.quosures rlang
## print.quosures rlang
## ── Attaching packages ─────────────────────────────────────────────────────── tidyverse 1.2.1 ──
## ✔ ggplot2 3.1.1 ✔ purrr 0.3.2
## ✔ tibble 2.1.1 ✔ dplyr 0.8.3
## ✔ tidyr 1.0.0 ✔ stringr 1.4.0
## ✔ readr 1.3.1 ✔ forcats 0.4.0
## ── Conflicts ────────────────────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
religion <- read_sav("http://www.losmexicanos.unam.mx/religion/encuesta_nacional/base_datos/Encuesta_Nacional_de_Religion_Secularizacion_y_Laicidad.sav")
religion
## # A tibble: 1,200 x 268
## Con1 edo muni loca ageb hr_ini1 min_ini1 hr_ter1 min_ter1 dura1
## <dbl> <dbl> <dbl> <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 2 2 289 414-9 12 23 12 42 19
## 2 2 2 2 289 414-9 12 22 12 41 19
## 3 3 2 2 289 414-9 12 22 12 45 23
## 4 4 2 2 289 414-9 12 48 13 4 16
## 5 5 2 2 289 414-9 12 50 13 11 21
## 6 6 2 2 289 414-9 12 43 13 2 19
## 7 7 2 2 289 414-9 13 6 13 29 23
## 8 8 2 2 289 414-9 13 18 13 36 18
## 9 9 2 2 289 414-9 13 4 13 22 18
## 10 10 2 2 289 414-9 13 34 13 53 19
## # … with 1,190 more rows, and 258 more variables: resul1 <dbl>,
## # hr_ini2 <dbl>, min_ini2 <dbl>, hr_ter2 <dbl>, min_ter2 <dbl>,
## # dura2 <dbl>, resul2 <dbl>, hr_ini3 <dbl>, min_ini3 <dbl>,
## # hr_ter3 <dbl>, min_ter3 <dbl>, dura3 <dbl>, resul3 <dbl>,
## # hr_ini4 <dbl>, min_ini4 <dbl>, hr_ter4 <dbl>, min_ter4 <dbl>,
## # dura4 <dbl>, resul4 <dbl>, p1_1 <dbl+lbl>, p1_2 <dbl+lbl>,
## # p1_3 <dbl+lbl>, p2 <dbl+lbl>, p3 <dbl+lbl>, p4 <dbl+lbl>,
## # p5 <dbl+lbl>, p6 <dbl+lbl>, p7_1 <dbl+lbl>, p7_2 <dbl+lbl>,
## # p7_3 <dbl+lbl>, p8_1 <dbl+lbl>, p8_2 <dbl+lbl>, p8_3 <dbl+lbl>,
## # p8_4 <dbl+lbl>, p8_5 <dbl+lbl>, p9_1 <dbl+lbl>, p9_2 <dbl+lbl>,
## # p9_3 <dbl+lbl>, p10 <dbl+lbl>, p11 <dbl+lbl>, p12 <dbl+lbl>,
## # p13_1 <dbl+lbl>, p13_2 <dbl+lbl>, p13_3 <dbl+lbl>, p14 <dbl+lbl>,
## # p15 <dbl+lbl>, p16_1 <dbl+lbl>, p16_2 <dbl+lbl>, p16_3 <dbl+lbl>,
## # p16_4 <dbl+lbl>, p17_1 <dbl+lbl>, p17_2 <dbl+lbl>, p17_3 <dbl+lbl>,
## # p17_4 <dbl+lbl>, p17_5 <dbl+lbl>, p17_6 <dbl+lbl>, p17_7 <dbl+lbl>,
## # p17_8 <dbl+lbl>, p17_9 <dbl+lbl>, p17_10 <dbl+lbl>, p17_11 <dbl+lbl>,
## # p17_12 <dbl+lbl>, p17_13 <dbl+lbl>, p17_14 <dbl+lbl>,
## # p17_15 <dbl+lbl>, p17_16 <dbl+lbl>, p18 <dbl+lbl>, p19 <dbl+lbl>,
## # p20 <dbl+lbl>, p21 <dbl+lbl>, p22_1 <dbl+lbl>, p22_2 <dbl+lbl>,
## # p22_3 <dbl+lbl>, p23 <dbl+lbl>, p24 <dbl+lbl>, p25 <dbl+lbl>,
## # p26 <dbl+lbl>, p27_1 <dbl+lbl>, p27_2 <dbl+lbl>, p27_3 <dbl+lbl>,
## # p27_4 <dbl+lbl>, p27_5 <dbl+lbl>, p27_6 <dbl+lbl>, p27_7 <dbl+lbl>,
## # p27_8 <dbl+lbl>, p28_1 <dbl+lbl>, p28_2 <dbl+lbl>, p28_3 <dbl+lbl>,
## # p28_4 <dbl+lbl>, p28_5 <dbl+lbl>, p28_6 <dbl+lbl>, p28_7 <dbl+lbl>,
## # p28_8 <dbl+lbl>, p28_9 <dbl+lbl>, p28_10 <dbl+lbl>, p28_11 <dbl+lbl>,
## # p28ot1 <dbl+lbl>, p28ot2 <dbl+lbl>, p28ot3 <dbl+lbl>,
## # p28ot4 <dbl+lbl>, …
# Atributo de etiqueta de una columna
attr(religion$p7_1, "label")
## [1] " 7. ¿En cuáles de los siguientes lugares recibió una educación religiosa? 1° MENCIÓN"
diccionario <- tibble(nombre = colnames(religion),
etiqueta = map_chr(religion, attr, "label"))
diccionario
## # A tibble: 268 x 2
## nombre etiqueta
## <chr> <chr>
## 1 Con1 ID
## 2 edo " Estado"
## 3 muni " Municipio"
## 4 loca " Localidad"
## 5 ageb AGEB
## 6 hr_ini1 " Hora inicio"
## 7 min_ini1 " Minutos de inicio"
## 8 hr_ter1 " Hora de termino"
## 9 min_ter1 " Minutos de termino"
## 10 dura1 " Duración"
## # … with 258 more rows
#View(diccionario)
Obtenemos una estructura de datos relacional de pares y valores. Como mínimo nos sirve para consultar la definición de una variable, pero también podemos usarlo como una tabla para cambiar de nombres a etiquetas. De este modo podemos hacer la mayor parte del procesamiento usando los nombres cortos y luego renombrar a las columnas justo antes de utilizar una función en la que sirvan los nombres largos.
La función renombrar()
tiene como único argumento un data.frame (que puede ser un subconjunto del data.frame completo) y utiliza las equivalencias del diccionario para renombrar.
renombrar <- function(x) {
rename_all(x, ~diccionario$etiqueta[match(., diccionario$nombre)])
}
religion %>%
select(p43_1, p43_2) %>%
renombrar()
## # A tibble: 1,200 x 2
## ` 43. ¿Qué tan de acuerdo o en desa… ` 43. ¿Qué tan de acuerdo o en des…
## <dbl+lbl> <dbl+lbl>
## 1 1 [De acuerdo] 1 [De acuerdo]
## 2 1 [De acuerdo] 2 [De acuerdo en parte (esp.)]
## 3 98 [NS] 98 [NS]
## 4 1 [De acuerdo] 1 [De acuerdo]
## 5 1 [De acuerdo] 1 [De acuerdo]
## 6 1 [De acuerdo] 1 [De acuerdo]
## 7 1 [De acuerdo] 1 [De acuerdo]
## 8 5 [En desacuerdo] 5 [En desacuerdo]
## 9 1 [De acuerdo] 1 [De acuerdo]
## 10 1 [De acuerdo] 2 [De acuerdo en parte (esp.)]
## # … with 1,190 more rows
También se puede utilizar left_join()
para renombrar los valores de un data.frame en formato largo o formato de pares de clave-valor.
tolerancia <- religion %>%
select(p43_1, p43_2) %>%
as_factor() %>%
pivot_longer(cols = everything(),
names_to = "nombre") # "nombre" coincide con la columna en el diccionario
tolerancia %>%
left_join(diccionario)
## Joining, by = "nombre"
## # A tibble: 2,400 x 3
## nombre value etiqueta
## <chr> <fct> <chr>
## 1 p43_1 De acuerdo " 43. ¿Qué tan de acuerdo o en desacuerdo est…
## 2 p43_2 De acuerdo " 43. ¿Qué tan de acuerdo o en desacuerdo est…
## 3 p43_1 De acuerdo " 43. ¿Qué tan de acuerdo o en desacuerdo est…
## 4 p43_2 De acuerdo en par… " 43. ¿Qué tan de acuerdo o en desacuerdo est…
## 5 p43_1 NS " 43. ¿Qué tan de acuerdo o en desacuerdo est…
## 6 p43_2 NS " 43. ¿Qué tan de acuerdo o en desacuerdo est…
## 7 p43_1 De acuerdo " 43. ¿Qué tan de acuerdo o en desacuerdo est…
## 8 p43_2 De acuerdo " 43. ¿Qué tan de acuerdo o en desacuerdo est…
## 9 p43_1 De acuerdo " 43. ¿Qué tan de acuerdo o en desacuerdo est…
## 10 p43_2 De acuerdo " 43. ¿Qué tan de acuerdo o en desacuerdo est…
## # … with 2,390 more rows
Aparece la columnaetiqueta
con la descripción de la variable. Sin embargo tiene un problema: hay un espacio delante y otro detrás de la descripción que luce un poco mal. Además el nombre es demasiado largo, lo que complicará el etiquetado si queremos usarlo para un gráfico.
tolerancia %>%
left_join(diccionario) %>%
mutate(etiqueta = str_remove(etiqueta, "43. ¿Qué tan de acuerdo o en desacuerdo está usted con las siguientes ideas\\? "),
etiqueta = str_trim(etiqueta),
etiqueta = str_wrap(etiqueta, 40)) %>%
group_by(value, etiqueta) %>%
count() %>%
ggplot(aes(x=str_wrap(value, 15), y = n)) +
geom_col() +
facet_wrap(vars(etiqueta), ncol = 1) +
theme_minimal() +
labs(title = "¿Qué tan de acuerdo o en desacuerdo está usted con las\nsiguientes ideas?",
y = NULL)
## Joining, by = "nombre"
¿Qué es dbl+lbl
?
Algunas de las columnas de este data.frame pertenecen a una clase algo inusual: dbl+lbl
. El signo +
indica que pertenecen a dos clases al mismo tiempo, son double
o número no enteros y son labelled
o variable etiquetadas. Unas pocas funciones1 reconocen esta dualidad y la pueden manejar. La mayoría de las funciones base ignoran esa clase especial y consideran a estos vectores como numéricos, algo que no es necesariamente una buena idea para variable categóricas. La función as_factor()
2 se encarga de convertir un vector dbl+lbl
en un factor común y corriente de R
. Esta función aprovecha la orientación a objetos de R
y tiene métodos para diferentes clases de objetos, por lo que podemos usarla de igual modo para un data.frame completo y para un vector.
Combinaciones bivariadas
Cuando estamos explorando una base de datos puede ser interesante hacer un análisis bivariado de un conjunto de datos de interés. Pensemos en tres casos 1) hacer gráficos de pares, 2) producir las tablas de contingencia de todos los posibles pares de variables en un data.frame con datos categóricos o 3) estimar el coeficiente de correlación entre todos los posibles pares de variables.
Los casos 1 y 3 ya están contemplados en R
. La función pairs
o, mejor aún, GGally::ggpairs()
resuelven el caso 1, generando un gráfico con todos los pares de variables. La función cor()
por defecto produce una matriz de correlación en la que cada celda contiene el coeficiente de correlación para cada par de variables, resolviendo el caso 3.
¿Qué pasa con el caso 2? No hay una función que se encargue de resolver ese problema de manera genérica. Por lograrlo lo más simple, robusto y generalizable es crear una lista, en la que cada elemento es un par de variables. La función listar_pares()
, que se define más abajo, hace exactamente eso: toman un data.frame y, por defecto, nos regresa una lista de data.frame con todas combinaciones únicas de dos columnas.
El argumento full = TRUE
produce una lista con el producto cartesiano de todas las variables, incluyendo los cruces de cada variable consigo misma y cruces repetidos, en los que cada variable ocupa el primer lugar cada vez. Esto podría ser útil para generar una matriz completa de estadísticos o gráficos bivariados.
El resultado en ambos casos es, por defecto, una lista nombrada. El nombre de cada elemento de la lista es el concatenado de los nombres separado por el símbolo /
. Si los nombres son innecesario o directamente un estorbo se puede utilizar la funciónunname()
para eliminarlos.
Tomemos el bloque p44
de la base de datos religión. Para mantener las cosas simples nos enfocamos en las primeras 3, aunque podrías hacer esto mismo para muchas más variables.
#Subconjunto de datos sobre tolerancia
religion %>%
select(p44_1:p44_3) %>%
as_factor() -> tolerancia
lista_pares <- function(df, full = FALSE) {
if(!full) {
nombres <- combn(names(df), 2, simplify = FALSE)
}
else
{
nombres <- lapply(apply(expand.grid(names(df), names(df), stringsAsFactors = FALSE), 1, as.list), as.character)
}
out <- lapply (nombres, function (x) {df[, c(x[1], x[2])]})
names(out) <- lapply(nombres, paste, collapse = " / ")
out
}
lista_pares(tolerancia)
## $`p44_1 / p44_2`
## # A tibble: 1,200 x 2
## p44_1 p44_2
## <fct> <fct>
## 1 Ni tolerante ni intolerante (esp.) Ni tolerante ni intolerante (esp.)
## 2 Tolerante Tolerante
## 3 NC NC
## 4 Tolerante Tolerante
## 5 Tolerante Tolerante
## 6 Tolerante Tolerante
## 7 Tolerante Tolerante
## 8 Ni tolerante ni intolerante (esp.) Ni tolerante ni intolerante (esp.)
## 9 Tolerante Tolerante
## 10 Tolerante Tolerante
## # … with 1,190 more rows
##
## $`p44_1 / p44_3`
## # A tibble: 1,200 x 2
## p44_1 p44_3
## <fct> <fct>
## 1 Ni tolerante ni intolerante (esp.) Ni tolerante ni intolerante (esp.)
## 2 Tolerante Tolerante
## 3 NC NC
## 4 Tolerante Tolerante
## 5 Tolerante Tolerante
## 6 Tolerante Tolerante
## 7 Tolerante Tolerante
## 8 Ni tolerante ni intolerante (esp.) Ni tolerante ni intolerante (esp.)
## 9 Tolerante Tolerante
## 10 Tolerante Tolerante
## # … with 1,190 more rows
##
## $`p44_2 / p44_3`
## # A tibble: 1,200 x 2
## p44_2 p44_3
## <fct> <fct>
## 1 Ni tolerante ni intolerante (esp.) Ni tolerante ni intolerante (esp.)
## 2 Tolerante Tolerante
## 3 NC NC
## 4 Tolerante Tolerante
## 5 Tolerante Tolerante
## 6 Tolerante Tolerante
## 7 Tolerante Tolerante
## 8 Ni tolerante ni intolerante (esp.) Ni tolerante ni intolerante (esp.)
## 9 Tolerante Tolerante
## 10 Tolerante Tolerante
## # … with 1,190 more rows
lista_pares(tolerancia) %>%
map(table)
## $`p44_1 / p44_2`
## p44_2
## p44_1 Tolerante
## Tolerante 704
## Ni tolerante ni intolerante (esp.) 27
## Intolerante 12
## NA 1
## NS 1
## NC 0
## p44_2
## p44_1 Ni tolerante ni intolerante (esp.)
## Tolerante 150
## Ni tolerante ni intolerante (esp.) 162
## Intolerante 18
## NA 1
## NS 0
## NC 1
## p44_2
## p44_1 Intolerante NA NS NC
## Tolerante 24 3 4 0
## Ni tolerante ni intolerante (esp.) 8 0 1 0
## Intolerante 53 1 4 0
## NA 1 6 0 0
## NS 0 0 11 0
## NC 0 0 0 7
##
## $`p44_1 / p44_3`
## p44_3
## p44_1 Tolerante
## Tolerante 591
## Ni tolerante ni intolerante (esp.) 39
## Intolerante 10
## NA 3
## NS 1
## NC 1
## p44_3
## p44_1 Ni tolerante ni intolerante (esp.)
## Tolerante 202
## Ni tolerante ni intolerante (esp.) 135
## Intolerante 19
## NA 0
## NS 0
## NC 0
## p44_3
## p44_1 Intolerante NA NS NC
## Tolerante 71 0 16 5
## Ni tolerante ni intolerante (esp.) 17 0 6 1
## Intolerante 54 0 5 0
## NA 0 6 0 0
## NS 0 0 11 0
## NC 0 0 0 7
##
## $`p44_2 / p44_3`
## p44_3
## p44_2 Tolerante
## Tolerante 563
## Ni tolerante ni intolerante (esp.) 69
## Intolerante 9
## NA 2
## NS 2
## NC 0
## p44_3
## p44_2 Ni tolerante ni intolerante (esp.)
## Tolerante 122
## Ni tolerante ni intolerante (esp.) 214
## Intolerante 17
## NA 2
## NS 1
## NC 0
## p44_3
## p44_2 Intolerante NA NS NC
## Tolerante 43 0 12 5
## Ni tolerante ni intolerante (esp.) 42 0 6 1
## Intolerante 56 0 4 0
## NA 0 6 0 0
## NS 1 0 16 0
## NC 0 0 0 7
lista_pares(tolerancia) %>%
map(set_names, c("izq", "der")) %>%
bind_rows(.id = "cruce") %>%
group_by(cruce, izq, der) %>%
count()
## # A tibble: 64 x 4
## # Groups: cruce, izq, der [64]
## cruce izq der n
## <chr> <fct> <fct> <int>
## 1 p44_1 / p4… Tolerante Tolerante 704
## 2 p44_1 / p4… Tolerante Ni tolerante ni intoleran… 150
## 3 p44_1 / p4… Tolerante Intolerante 24
## 4 p44_1 / p4… Tolerante NA 3
## 5 p44_1 / p4… Tolerante NS 4
## 6 p44_1 / p4… Ni tolerante ni intolerant… Tolerante 27
## 7 p44_1 / p4… Ni tolerante ni intolerant… Ni tolerante ni intoleran… 162
## 8 p44_1 / p4… Ni tolerante ni intolerant… Intolerante 8
## 9 p44_1 / p4… Ni tolerante ni intolerant… NS 1
## 10 p44_1 / p4… Intolerante Tolerante 12
## # … with 54 more rows
Convertir una matriz de indicadores en un factor
En algunos casos cuando importamos datos categóricos las variables no están en una solo columna, sino que tienen la forma de una matriz de indicadores: cada categoría es una variable y un registro (TRUE
, 1
, Sí
o la etiqueta correspondiente a la categoría) indican en datos. Este es un formato incómodo para trabajar en R
, lo ideal es tener a cada variable en una columna.
Aunque el problema puede tener diferentes casos una buena alternativa para resolver este problema, que puede adaptarse a diferentes situaciones, es utilizar la función coalesce()
.
Para poder ejemplificar el proceso comenzaremos por simular unos datos con esta estructura. Tendremos la Pregunta 1, que simula una escala de Likert con cuatro categorías y la Pregunta 2, con idénticas categorías. Ambas se generan con un proceso aleatorio independiente y se reúnen en el mismo data.frame. El proceso de simular los datos es algo complicado, lo importante es que el resultado de el data.frame que vamos a limpiar juntando las cuatro columnas en una sola.
Nota Si alguien piensa que este es un ejemplo innecesariamente retorcido jamás ha recibido una base de datos cargada en Excel.
categorías <- c("Muy de acuerdo", "De acuerdo", "En desacuerdo", "Muy en desacuerdo")
pregunta1 <- sample(categorías,
size = 100,
prob = c(0.2, 0.2, 0.5, 0.1),
replace = TRUE)
df1 <- lapply(categorías, function(x) ifelse(pregunta1 == x, x, NA)) %>%
as.data.frame() %>%
setNames(paste0("Pregunta1", categorías))
pregunta2 <- sample(categorías,
size = 100,
prob = c(0.2, 0.2, 0.5, 0.1),
replace = TRUE)
df2 <- lapply(categorías, function(x) ifelse(pregunta2 == x, x, NA)) %>%
as.data.frame() %>%
setNames(paste0("Pregunta2", categorías))
df_final <- cbind(df1, df2)
as_tibble(df_final)
## # A tibble: 100 x 8
## `Pregunta1Muy d… `Pregunta1De ac… `Pregunta1En de… `Pregunta1Muy e…
## <fct> <fct> <fct> <fct>
## 1 <NA> <NA> En desacuerdo <NA>
## 2 Muy de acuerdo <NA> <NA> <NA>
## 3 Muy de acuerdo <NA> <NA> <NA>
## 4 <NA> <NA> En desacuerdo <NA>
## 5 <NA> <NA> En desacuerdo <NA>
## 6 <NA> De acuerdo <NA> <NA>
## 7 <NA> <NA> En desacuerdo <NA>
## 8 <NA> <NA> En desacuerdo <NA>
## 9 <NA> <NA> En desacuerdo <NA>
## 10 <NA> <NA> <NA> Muy en desacuer…
## # … with 90 more rows, and 4 more variables: `Pregunta2Muy de
## # acuerdo` <fct>, `Pregunta2De acuerdo` <fct>, `Pregunta2En
## # desacuerdo` <fct>, `Pregunta2Muy en desacuerdo` <fct>
Buscamos una data.frame con dos columnas, Pregunta 1
y Pregunta 2
. La función coalesce()
hará el trabajo pesado: juntar los vectores reemplazando los NA
(missing) con un registro válido del otro vector. Como esta función trabaja solamente con pares es necesario aplicarla con un funcional que recorra una lista resolviendo el primer par y luego, sobre el resultado de ese par, resolverlo con el vector siguiente. Y así recursivamente hasta agotar la lista. Esta operación llamada reducción es frecuente en la programación funcional. La función reduce()
es una de las aplicaciones en R
de la reducción de listas.
Como tenemos dos grupos de columnas hay un paso previo necesario: separar a cada grupo y ubicarlo como elemento de una lista. La función split.default()
combinada con una expresión regular que nos permite separar la parte variable del nombre de columnas (en este caso Pregunta1
y Pregunta2
) de la parte constante (la categoría de respuesta).
df_final %>%
mutate_all(as.character) %>% #coalesce fallará con factores
split.default(str_remove(names(.),
#subnombres separados por | (o en expresiones regulares)
"Muy de acuerdo|De acuerdo|En desacuerdo|Muy en desacuerdo")) %>%
map_df(reduce, coalesce)
## # A tibble: 100 x 2
## Pregunta1 Pregunta2
## <chr> <chr>
## 1 En desacuerdo En desacuerdo
## 2 Muy de acuerdo En desacuerdo
## 3 Muy de acuerdo Muy de acuerdo
## 4 En desacuerdo De acuerdo
## 5 En desacuerdo En desacuerdo
## 6 De acuerdo En desacuerdo
## 7 En desacuerdo De acuerdo
## 8 En desacuerdo En desacuerdo
## 9 En desacuerdo Muy en desacuerdo
## 10 Muy en desacuerdo En desacuerdo
## # … with 90 more rows