Los barómetros del CIS “se realizan con una periodicidad mensual –excepto los meses de agosto– y tienen como principal objetivo medir el estado de la opinión pública española del momento. Para ello se entrevista en torno a 2.500 personas elegidas al azar dentro del territorio nacional, de las que, además de sus opiniones, se recoge una amplia información social y demográfica para el análisis”.
El objetivo de este proyecto es facilitar el análisis y visualización de los datos de los barómetros del CIS.
Análisis de microdatos
Los datos que estamos intentando convertir a formato abierto y manejable (archivo de texto plano, etc) son los contenidos en el archivo .sav (https://en.wikipedia.org/wiki/PSPP) de cualquiera de los barómetros del CIS (ejemplo de barómetro, enero 2018). Estos datos contienen las respuestas de las 2.400+ personas encuestadas (también llamados microdatos).
Obtención de datos
Por cada barómetro hay descargables varios archivos:
-
Resultados agregados (en PDF y en HTML)
-
Los cruces: una serie de archivos según variables sociodemográficas, políticas y socioeconómicas (en HTML)
-
Fichero_datos (.zip descargable previo relleno de formulario)
-
Ficha_técnica (PDF)
-
Cuestionario (PDF)
Sería posible scrapear la página para obtener los html con los resultados y los cruces. Luego habría que parsear esas páginas en html para guardar los datos en formatos reutilizables.
Para el caso de los microdatos (el total de las respuestas) hace falta rellenar un formulario (nombre y apellidos, email, objetivo de solicitud), por lo que un scrapeado sencillo no valdría. Supongo que el formulario está puesto para prevenir eso, precisamente. Podríamos contactar al CIS para preguntar si es posible que nos faciliten esos datos para hacer estudiar los datos masivamente.
Análisis de respuestas con R
Se puede usar la librería Foreign del programa R para leer un archivo .sav. Ejemplos: https://datascienceplus.com/get-your-data-into-r/
Leer un archivo .sav de PSPP con R:
install.packages("foreign") library(foreign) df <- read.spss("DA3203.sav", use.value.label=TRUE, to.data.frame=TRUE)
¿Cómo segmentar las respuestas por comunidad autónoma?
Creamos un data frame con los etiquetados en la variable comunidad autónoma (CCAA), por ejemplo:
euskadi ← df[df$CCAA==“País Vasco”,]
Para ver cuántas personas contestaron en primer lugar qué problemas a la pregunta de los “Tres problemas principales que existen actualmente en España” podemos usar table y la variable P701:
table(euskadi$P701)
Resultado:
El paro: 56 La corrupción y el fraude: 21 ... La educación: 1
Calcula el porcentaje de usuarios que contesta tal o cual pregunta
Esta página del CIS muestra el porcentaje de usuarios que respondieron cierto tema a la pregunta de los “Tres problemas principales que existen actualmente en España”: http://www.cis.es/cis/export/sites/default/-Archivos/Indicadores/documentos_html/TresProblemas.html
En el barómetro de enero 2018, el 6,8% de encuestados que respondieron “La educación” en una de sus tres respuestas se calcularía así con R:
(nrow(df[df$P701=="La educación",]) + # total de encuestados responden en primer lugar "La educación" nrow(df[df$P702=="La educación",]) + # total en 2º lugar nrow(df[df$P703=="La educación",]) # total en tercer lugar ) / nrow(df)*100 # dividido por el total de encuestados
El resultado es:
[1] 6.822769
Otros / Cajón de sastre
Licencia de uso de los datos del CIS
Según se especifica cuando los descargas:
Así que no podemos hacer un repositorio público de sus datos re-abiertos ¿pero sí publicar las instrucciones de cómo hacer eso en tu ordenador local?
Visualización de trasvase de votos
Las visualizaciones de trasvase de votos más frecuentes son la representación de un cruce de dos variables: recuerdo de voto e intención de voto. Este tipo de visualizaciones se suelen representar como un diagrama sankey. Para hacer un diagrama sankey es necesario crear dos tablas de datos: una con los identificadores de los nodos (p. ej.: Unidos Podemos, PSOE, etc…) y otra con los vectores (p. ej.: Unidos Podemos → PSOE) y el valor asociado a este (p. ej.: 9,8%).
A continuación un script para importar el último barómetro del CIS con intención de voto, crear una tabla de frecuencias del cruce de las variables recuerdo de voto el 26J e intención de voto+simpatía, y crear el diagrama sankey con la librería networkD3.
# Importamos las librerías. Si no las tenemos instaladas hay que instalarlas con la funcion install.packages() para cada una de las librerias library(foreign) library(tidyverse) library(networkD3) setwd("RUTA-AL-DIRECTORIO-DE-TRABAJO") # Indicamos la ruta en nuestro ordenador donde está la matriz del CIS cis <- read.spss("MD3210/3210.sav", use.value.label=TRUE, to.data.frame=TRUE) # Importamos la matriz del CIS p <- cis %>% group_by(RECUERDO, VOTOSIMG) %>% summarise(N = n()) %>% mutate(pct = N/sum(N)) # creamos la tabla de frecuencias del cruce p <- p[!is.na(p$RECUERDO),] # Eliminamos los NA # Recodificamos las variables para juntar las confluencias con Unidos Podemos p$RECUERDO[p$RECUERDO %in% c("En Marea", "En Comú Podem", "Compromís-Podemos-EUPV")] <- "Unidos Podemos" p$VOTOSIMG[p$VOTOSIMG %in% c("En Marea", "En Comú Podem", "Compromís-Podemos")] <- "Unidos Podemos" links <- data.frame(p) # Convertimos la tabla de frecuencias a un data.frame links$VOTOSIMG <- paste0(links$VOTOSIMG, "_") # Añadimos un guión bajo en una de las columnas para que la funcion sankeyNetwork reconozca como nodos independientes el recuerdo de voto y la intencion de voto names(links) = c("source", "target", "value", "value_pct") # renombramos las columnas nodes <- data.frame(name = unique(c(as.character(links$source), as.character(links$target)))) # Creamos un data.fram con los identificadores de los nodos # En la tabla de links cambiamos las etiquetas de los partidos por sus respectivo ids de la tabla de nodos links$source <- match(links$source, nodes$name) - 1 links$target <- match(links$target, nodes$name) - 1 # Ejecutamos la funcion para crear el diagrama sankey sankeyNetwork(Links = links, Nodes = nodes, Source = "source", Target = "target", Value = "value", NodeID = "name", fontSize= 10, nodeWidth = 5)