Usando R para descargar archivos de datos comprimidos, extraer e importar datos

122

@EZGraphs en Twitter escribe: "Muchos csvs en línea están comprimidos. ¿Hay alguna manera de descargar, descomprimir el archivo y cargar los datos en un data.frame usando R? #Rstats"

También estaba tratando de hacer esto hoy, pero terminé descargando el archivo zip manualmente.

Intenté algo como:

fileName <- "http://www.newcl.org/data/zipfiles/a1.zip"
con1 <- unz(fileName, filename="a1.dat", open = "r")

pero siento que estoy muy lejos. ¿Alguna idea?

Jeromy Anglim
fuente
¿Funcionó? Si es así, ¿por qué aún sentirías que estás muy lejos?
FrustratedWithFormsDesigner
@ Frustrado ... No. El código en mi pregunta no funciona. Ver las respuestas a continuación.
Jeromy Anglim

Respuestas:

176

Los archivos zip son en realidad más un 'sistema de archivos' con metadatos de contenido, etc. Consulte help(unzip)para más detalles. Entonces, para hacer lo que bosquejas arriba necesitas

  1. Crea una temperatura. nombre de archivo (por ejemplo tempfile())
  2. Use download.file()para buscar el archivo en la temperatura. expediente
  3. Use unz()para extraer el archivo de destino de temp. expediente
  4. Eliminar el archivo temporal a través de unlink()

que en el código (gracias por el ejemplo básico, pero esto es más simple) parece

temp <- tempfile()
download.file("http://www.newcl.org/data/zipfiles/a1.zip",temp)
data <- read.table(unz(temp, "a1.dat"))
unlink(temp)

Los archivos comprimidos ( .z) o gzipped ( .gz) o bzip2ed ( .bz2) son solo el archivo y los que puede leer directamente desde una conexión. Así que haga que el proveedor de datos lo use en su lugar :)

Dirk Eddelbuettel
fuente
Dirk, ¿te importaría ampliar cómo extraer datos de un .zarchivo? Puedo leer desde una conexión URL con readBin(url(x, "rb"), 'raw', 99999999), pero ¿cómo extraería los datos contenidos? El uncompresspaquete se ha eliminado de CRAN. ¿Es esto posible en la base R (y si es así, ¿está restringido a los sistemas * nix?)? Feliz de publicar como una nueva pregunta, si corresponde.
jbaums
3
Mira help(gzfile), estaba pensando que el protocolo gzip ahora también puede descomprimir (viejos) archivos .z ahora que la patente ha expirado hace mucho tiempo. Puede que no. ¿Quién usa .z de todos modos? Los años 80 llamaron, quieren recuperar su compresión ;-)
Dirk Eddelbuettel
Gracias, no puedo hacer que funcione, así que tal vez no sea compatible después de todo. ¡La Oficina Australiana de Meteorología proporciona algunos de sus datos como .z, por desgracia!
jbaums
FYI No funciona con readRDS()(al menos para mí). Por lo que puedo decir, el archivo debe estar en un tipo de archivo con el que pueda leer read.table().
jessi
1
También querrás cerrar la conexión. R solo puede tener 125 abiertos a la vez. Algo así como con <- unz (temp, "a1.dat"); datos <- read.table (con); cerrar (con);
pdb
28

Solo para que conste, intenté traducir la respuesta de Dirk al código :-P

temp <- tempfile()
download.file("http://www.newcl.org/data/zipfiles/a1.zip",temp)
con <- unz(temp, "a1.dat")
data <- matrix(scan(con),ncol=4,byrow=TRUE)
unlink(temp)
George Dontas
fuente
55
No utilizar scan(); puede usar read.table()et al directamente en una conexión. Vea mi respuesta editada,
Dirk Eddelbuettel
17

Utilicé el "descargador" del paquete CRAN que se encuentra en http://cran.r-project.org/web/packages/downloader/index.html . Más fácil.

download(url, dest="dataset.zip", mode="wb") 
unzip ("dataset.zip", exdir = "./")
unixcreeper
fuente
2
Acabo de usar utils :: descomprimir sin necesidad del paquete de
descarga
a partir de 2019: tenía que decir exdir = '.'
userJT
9

Para Mac (y supongo que Linux) ...

Si el archivo zip contiene un solo archivo, puede usar el comando bash funzip, junto con freadel del data.tablepaquete:

library(data.table)
dt <- fread("curl http://www.newcl.org/data/zipfiles/a1.zip | funzip")

En los casos en que el archivo contiene varios archivos, puede usar taren su lugar para extraer un archivo específico para stdout:

dt <- fread("curl http://www.newcl.org/data/zipfiles/a1.zip | tar -xf- --to-stdout *a1.dat")
dnlbrky
fuente
cuando probé su solución para varios archivos, recibo un error queFile is empty:
bshelt141
9

Aquí hay un ejemplo que funciona para archivos que no se pueden leer con la read.tablefunción. Este ejemplo lee un archivo .xls.

url <-"https://www1.toronto.ca/City_Of_Toronto/Information_Technology/Open_Data/Data_Sets/Assets/Files/fire_stns.zip"

temp <- tempfile()
temp2 <- tempfile()

download.file(url, temp)
unzip(zipfile = temp, exdir = temp2)
data <- read_xls(file.path(temp2, "fire station x_y.xls"))

unlink(c(temp, temp2))
ColinTea
fuente
5

Para hacer esto usando data.table, descubrí que lo siguiente funciona. Desafortunadamente, el enlace ya no funciona, así que usé un enlace para otro conjunto de datos.

library(data.table)
temp <- tempfile()
download.file("https://www.bls.gov/tus/special.requests/atusact_0315.zip", temp)
timeUse <- fread(unzip(temp, files = "atusact_0315.dat"))
rm(temp)

Sé que esto es posible en una sola línea, ya que puede pasar scripts de bash a fread, pero no estoy seguro de cómo descargar un archivo .zip, extraer y pasar un solo archivo desde allí fread.

Mallick Hossain
fuente
4

Prueba este código. Esto funciona para mi:

unzip(zipfile="<directory and filename>",
      exdir="<directory where the content will be extracted>")

Ejemplo:

unzip(zipfile="./data/Data.zip",exdir="./data")
Marcelo Tibau
fuente