Leer datos del CIS en R
20 October 2013

No trabajo habitualmente con datos del CIS. Por lo general, únicamente descargo datos cuando me interesa algo muy concreto que quiero comprobar. Cosas del estilo “¿Es cierto qué…?” y similares. Por ejemplo, estos días estoy intrigado con el debate sobre la relación entre clase social y apoyo al independentismo catalán (v.g., 1, 2, 3 y 4). Sin embargo, uno de los mayores obstáculos que encuentro para satisfacer mi curiosidad es el hecho de que alguien en el CIS ha pensado que proveer los datos en fixed-width format con diccionarios para SAS y SPSS es una buena idea. No, no lo es. De hecho, es una de las peores formas de distribución de datos que se me ocurren, pero dejo ese debate para otro día.

Por lo general uso R para análisis rápidos. Eso implica que, con los datos del CIS, o bien me construyo un diccionario que asigne columnas a variables o bien traduzco los datos a un formato binario que R pueda interpretar a través del paquete foreign. Esta segunda alternativa es la más eficiente gracias a PSPP, una alternativa libre a SPSS. Las únicas transformaciones que son necesarias consisten en añadir una EOL al archivo de sintaxis, incluir una línea que permita que los datos sean exportados y cambiar el signo usado para separar decimales, ya que trabajo en una locale norteamericana.

Como esto es algo que hago con cierta frecuencia, he optado por ponerlo todo junto en una sencillísima función para R que hace un par de llamadas a sed e iconv a través de system().

read_cis <- function(syntaxf, dataf) {
    ## @syntaxf is the location of the syntax file (starting with ES)
    ## @dataf is the location of the data file (starting with DA)
    require(foreign)
     
    ## Add EOL to the last line
    system(paste("sed -i -e '$a\\'", syntaxf, sep = " "))
     
    ## Convert to utf8
    new_syntaxf <- paste("utf8_", basename(syntaxf), sep = "")
    out_syntaxf <- file.path(dirname(syntaxf), new_syntaxf)
    system(paste("iconv -f ISO-8859-1 -t UTF-8", 
                 syntaxf, ">", out_syntaxf, sep = " "))
     
    ## Create output file
    out_dataf <- paste(basename(dataf), ".sav", sep = "")
    exportline <- paste("SAVE OUTFILE='", basename(dataf), ".sav'.", sep = "")
    system(paste("echo", exportline, ">>", out_syntaxf, sep = " "))
     
    ## Replace commas with dots for decimals in datafile
    system(paste("sed -i -e 's/,/./g'", dataf, sep = " "))
     
    ## Run, damnit, run!
    cwd <- getwd()
    setwd(dirname(dataf))
    system(paste("pspp", basename(out_syntaxf), sep = " "), wait = TRUE)
    setwd(cwd)
     
    ## Read SAV file 
    outdf <- read.spss(file.path(dirname(dataf), out_dataf), 
    to.data.frame = TRUE, use.value.labels = FALSE)
    return(outdf)
}

La función está diseñada para mi uso particular, así que no tengo ninguna intención de abstraerla más. Se podría generalizar para casos en los que el usuario prefiera no omitir las etiquetas de los datos o tenga debilidad por una codificación distinta de UTF-8. Quizás sería también conveniente añadir un par de cláusulas try para gestionar posibles errores en el archivo de sintaxis. Todos estos cambios los dejo para quien venga detrás.

Una nota final. Con los datos ya en R, guardarlos en otro formato amigable para, por ejemplo, Stata, se reduce a una simple llamada a foreign::write.dta().