¿Cómo votan los diputados?

Tras leer el otro día Visualizando la matriz de acuerdo legislativo, pensé que esta bitácora no podía quedarse atrás. Casi desisto. Pero cerrando ya casi el navegador vi que en la página de las votaciones del Congreso de los Diputados había dos enlaces aprovechables: en uno ponía XML y en el otro, “histórico”.

He aquí pues el código concomitante que fue apareciendo en mi sesión de RStudio:

library(XML)
library(reshape)
library(corrgram)
library(psych)

# descarga y manipulación de datos

dia.votacion <- function( n.votacion ){
    dir.create("tmp")
    url <- paste( "http://www.congreso.es/votaciones/OpenData?sesion=",
            n.votacion, "&completa=1&legislatura=10", sep = "" )
    download.file(url, destfile = "./tmp/votos.zip")
    try(unzip("./tmp/votos.zip", exdir = "./tmp"), TRUE)

    ficheros <- dir("./tmp", pattern = ".*xml", full.names = T )

    if ( length(ficheros ) == 0)
        return(NULL)

    res <- sapply(ficheros, function(fichero){
        datos <- xmlTreeParse(fichero)
        datos <- xmlToList(datos)$Votaciones

        if( is.null(datos) )
            return(NULL)

        datos <- as.data.frame(t(datos))
        datos <- as.data.frame(lapply( datos, unlist))
        },
        simplify = F
    )

    unlink( "./tmp", recursive = T)      # borra el directorio temporal

    res
}

res <- list()
for ( i in  1:54 ) res <- c( res, dia.votacion(i) )
# la 32, 33 está trucha
for ( i in 34:54 ) res <- c( res, dia.votacion(i) )

Con él se pueden bajar unas docenas de ficheros XML correspondientes a ciertos plenos de la X Legislatura, procesarlos mínimamente y guardarlos en la lista res. No estoy seguro de la profundidad histórica de los datos (aparentemente, sólo están disponibles los del 2012, aunque la X Legislatura arrancó, creo, antes). Además, falla la descarga de los ficheros correspondientes a las sesiones 32 y 33. Ese es el motivo por el que he tenido que recurrir a for, como los gañanes, en lugar de utiliza sapply, como era mi natural inclinación.

Haciendo

tmp <- res[ ! unlist(lapply(res, is.null) ) ]
names(tmp) <- paste( "votacion", 1:length(tmp), sep = "_")
tmp <- lapply( names(tmp), function(x) data.frame( votacion = x, tmp[[x]]))
votos <- do.call( rbind, tmp )
rownames(votos) <- NULL
votos <- votos[,-2]          # elimino el "asiento"

genero un objeto, votos, cuyas seis primeras filas tienen este aspecto:

votacion                            Diputado Voto
1 votacion_1          Muñoz González, Pedro José   Sí
2 votacion_1         González Vázquez, Sebastián   Sí
3 votacion_1                Ramis Socias, Miquel   Sí
4 votacion_1 Ares Martínez-Fortún, María de la O   Sí
5 votacion_1            Grau Reinés, Juan Carlos   Sí
6 votacion_1             Fajarnés Ribas, Enrique   Sí

En total, hay 350 diputados que han votado 438 asuntos.

Si uno hace

ausentes <- subset(votos, Voto == "No vota")
sort(table(ausentes$Diputado))

puede saber cuáles son los que han dejado de votar en más ocasiones por los motivos que sean. Dejaré que sean otros los que publiquen la salida de estas sentencias. Porque a mí me interesan más las correlaciones. Para lo cual, creo así

votos$ind <- 0
votos$ind[votos$Voto == "Sí"] <- 1
votos$ind[votos$Voto == "No"] <- -1

tmp <- subset(votos, select = -Voto)
tmp <- cast( votos, Diputado ~ votacion )

where.na <- apply( tmp, 1, function(x) any(is.na(x)))
tmp <- tmp[!where.na,]

matriz.votos <- as.matrix(tmp[,-1])

la matriz matriz.votos que tiene diputados en sus filas y votaciones en sus columnas. Esto permite representar mediante

cor.votos <- cor(t(matriz.votos))
cor.plot( mat.sort(cor.votos))

la matriz de correlaciones entre los sentidos de los votos de los distintos diputados,

en la que se aprecian claramente dos bloques diferenciados. Me llama la atención, en cualquier caso, la falta de tonos encarnados, muestra de pertinaz desacuerdo, en la figura. De hecho, la correlación más negativa, -0.45; la pareja de diputados tan desencontrados es la formada por Celia Alberto Pérez (PP) y Joan Baldoví, de un partido raro cuyo perfil leeré en la Wikipedia cuando encuentre un ratillo.

También puede hacerse un gráfico de calor,

heatmap(matriz.votos, xlab = "Asuntos", ylab = "Diputados", scale = "none")

que genera

y que reordena diputados por un lado y asuntos por el otro para mostrar de qué manera inciden los unos sobre los otros. Se aprecian bastante claramente los dos grandes grupos políticos y, para mi sorpresa, un par de bloques de asuntos relativamente amplios en los que votaron de acuerdo.

Los datos, estoy seguro, dan para muchas más cosas. Y tengo confianza en que alguien recogerá el guante y nos iluminará con incisivas preguntas y brillantes respuestas. Si en el camino piensa que puedo echarle una mano, que me escriba. Estaré encantado de ayudarle.