open - libreria foreign
Leer datos SAS sas7bdat en R (3)
¿Qué opciones tiene R para leer archivos en el formato SAS nativo, sas7bdat
, en R?
El NCES Common Core , por ejemplo, contiene un amplio repositorio de archivos de datos guardados en este formato. Para concretar, concentrémonos en tratar de leer this archivo de LEA Universe en 1997-98, que contiene información demográfica a nivel de agencia de educación para entidades en todos los estados que van desde la A hasta la I.
Aquí hay una vista previa de SAS de los datos:
¿Cuál es la forma más sencilla de llevar estos datos a mi entorno R? No tengo ninguna versión de SAS disponible y no estoy dispuesto a pagar, por lo que simplemente convertirlo a .csv sería una molestia.
Problema
El problema parece que los archivos que intentas usar están mal formateados. Específicamente, las celdas en blanco no están codificadas ( R
usa NA
) pero simplemente se dejan vacías. Cuando se intenta cargar el archivo delimitado por tabulaciones, esto crea problemas para R, que cree que hay un número incorrecto de columnas.
Solución utilizando archivos SAS
He encontrado una solución al cargar el archivo SAS con el paquete sas7bdat
y luego recodificar las celdas en blanco ( ""
) como NA:
install.packages("sas7bdat")
require("sas7bdat")
download.file("http://nces.ed.gov/ccd/Data/zip/ag121a_supp_sas.zip",
destfile = "sas.zip")
unzip("sas.zip")
sas <- read.sas7bdat(file = "ag121a_supp.sas7bdat", debug = FALSE)
sas[sas == ""] <- NA
Sin embargo, hay dos problemas con este método a tener en cuenta:
- Es lento (ver comentarios)
-
sas7bdat
paquetesas7bdat
actualmente se considera experimental al momento de escribirlo por su autor. Por lo tanto, es posible que no se carguen todos los archivos sas, y yo revisaría los que hace a fondo por inconsistencias antes de usarlos.
Solución no R
No es exactamente canónico, pero también puede descargar los archivos delimitados por tabuladores, abrirlos en LibreOffice Calc (parece que Microsoft Excel arruina las cosas) y buscar y reemplazar todos al buscar ""
y reemplazarlos con NA
.
A partir del 18 de enero de 2018, la biblioteca haven R cargará los conjuntos de datos sas y stata en el entorno R. En R, simplemente:
library(haven)
data <- read_sas("C:/temp/mysasdataset.sas7bdat")
View(data)
También puede cargar los datos manualmente dentro de R studio. En el panel de entorno, seleccione
Importar conjunto de datos> Desde SAS ...
Seleccione la ubicación del archivo y haga clic en "Importar"
sas7bdat
funcionó bien para todos menos uno de los archivos que estaba viendo (específicamente, este ); al informar el error al desarrollador de sas7bdat
, Matthew Shotwell, también me indicó la dirección del paquete de haven
de Hadley en R, que también tiene un método read_sas
.
Este método es superior por dos razones:
1) No tuve ningún problema en leer el archivo vinculado anteriormente 2) Es mucho (estoy hablando mucho ) más rápido que read.sas7bdat
. Aquí hay un punto de referencia rápido (en this archivo, que es más pequeño que los otros) para la evidencia:
microbenchmark(times=10L,
read.sas7bdat("psu97ai.sas7bdat"),
read_sas("psu97ai.sas7bdat"))
Unit: milliseconds
expr min lq mean median uq max neval cld
read.sas7bdat("psu97ai.sas7bdat") 66696.2955 67587.7061 71939.7025 68331.9600 77225.1979 82836.8152 10 b
read_sas("psu97ai.sas7bdat") 397.9955 402.2627 410.4015 408.5038 418.1059 425.2762 10 a
Así es haven::read_sas
toma (en promedio) 99.5% menos tiempo que sas7bdat::read.sas7bdat
.
actualización menor
Anteriormente no era capaz de averiguar si los dos métodos producían los mismos datos (es decir, que ambos tienen los mismos niveles de fidelidad con respecto a la lectura de los datos), pero finalmente lo han hecho:
# Keep as data.tables
sas7bdat <- setDT(read.sas7bdat("psu97ai.sas7bdat"))
haven <- setDT(read_sas("psu97ai.sas7bdat"))
# read.sas7bdat prefers strings as factors,
# and as of now has no stringsAsFactors argument
# with which to prevent this
idj_factor <- sapply(haven, is.factor)
# Reset all factor columns as characters
sas7bdat[ , (idj_factor) := lapply(.SD, as.character), .SDcols = idj_factor]
# Check equality of the tables
all.equal(sas7bdat, haven, check.attributes = FALSE)
# [1] TRUE
Sin embargo, tenga en cuenta que read.sas7bdat
ha mantenido una lista masiva de atributos para el archivo, probablemente un remanente de SAS:
str(sas7bdat)
# ...
# - attr(*, "column.info")=List of 70
# ..$ :List of 12
# .. ..$ name : chr "NCESSCH"
# .. ..$ offset: int 200
# .. ..$ length: int 12
# .. ..$ type : chr "character"
# .. ..$ format: chr "$"
# .. ..$ fhdr : int 0
# .. ..$ foff : int 76
# .. ..$ flen : int 1
# .. ..$ label : chr "UNIQUE SCHOOL ID (NCES ASSIGNED)"
# .. ..$ lhdr : int 0
# .. ..$ loff : int 44
# .. ..$ llen : int 32
# ...
Entonces, si por casualidad necesita estos atributos (sé que algunas personas están particularmente interesadas en las label
, por ejemplo), tal vez read.sas7bdat
es la opción para usted después de todo.