studio lenguaje large datasets data big r bigdata

r - lenguaje - python big data



Lectura de big data con ancho fijo. (3)

¿Cómo puedo leer big data formados con ancho fijo? Leí this pregunta y probé algunos consejos, pero todas las respuestas son para datos delimitados (como .csv), y ese no es mi caso. Los datos tienen 558MB, y no sé cuántas líneas.

Estoy usando:

dados <- read.fwf(''TS_MATRICULA_RS.txt'', width=c(5, 13, 14, 3, 3, 5, 4, 6, 6, 6, 1, 1, 1, 4, 3, 2, 9, 3, 2, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 4, 11, 9, 2, 3, 9, 3, 2, 9, 9, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1), stringsAsFactors=FALSE, comment.char='''', colClasses=c(''integer'', ''integer'', ''integer'', ''integer'', ''integer'', ''integer'', ''integer'', ''integer'', ''integer'', ''integer'', ''character'', ''character'', ''character'', ''integer'', ''integer'', ''character'', ''integer'', ''integer'', ''character'', ''integer'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character'', ''integer'', ''integer'', ''integer'', ''integer'', ''integer'', ''integer'', ''integer'', ''integer'', ''character'', ''integer'', ''integer'', ''character'', ''character'', ''character'', ''character'', ''integer'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character'', ''character''), buffersize=180000)

Pero toma 30 minutos (y contando ...) leer los datos. ¿Alguna sugerencia nueva?


Aquí hay una solución R pura que usa el nuevo paquete readr , creado por Hadley Wickham y el equipo RStudio, lanzado en abril de 2015. Más información here . El código es tan simple como esto:

library(readr) my.data.frame <- read_fwf(''TS_MATRICULA_RS.txt'', fwf_widths(c(5, 13, 14, 3, 3, 5, 4, 6, 6, 6, 1, 1, 1, 4, 3, 2, 9, 3, 2, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 4, 11, 9, 2, 3, 9, 3, 2, 9, 9, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1)), progress = interactive())

Ventajas de read_fwf{readr}

  • readr está basado en LaF pero sorprendentemente más rápido . Se ha demostrado que es el método más rápido para leer archivos de ancho fijo en R
  • Es más sencillo que las alternativas. por ejemplo, no tiene que preocuparse por column_types porque se imputarán a partir de las primeras 30 filas en la entrada.
  • Viene con una barra de progreso;)

El paquete LaF es bastante bueno para leer archivos de ancho fijo muy rápido. Lo uso a diario para cargar archivos de +/- 100Mio registros con 30 columnas (no tantas columnas de caracteres como tiene, principalmente datos numéricos y algunos factores). Y es bastante rápido. Así que esto es lo que yo haría.

library(LaF) library(ffbase) my.data.laf <- laf_open_fwf(''TS_MATRICULA_RS.txt'', column_widths=c(5, 13, 14, 3, 3, 5, 4, 6, 6, 6, 1, 1, 1, 4, 3, 2, 9, 3, 2, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 4, 11, 9, 2, 3, 9, 3, 2, 9, 9, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1), stringsAsFactors=FALSE, comment.char='''', column_types=c(''integer'', ''integer'', ''integer'', ''integer'', ''integer'', ''integer'', ''integer'', ''integer'', ''integer'', ''integer'', ''categorical'', ''categorical'', ''categorical'', ''integer'', ''integer'', ''categorical'', ''integer'', ''integer'', ''categorical'', ''integer'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''integer'', ''integer'', ''integer'', ''integer'', ''integer'', ''integer'', ''integer'', ''integer'', ''categorical'', ''integer'', ''integer'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''integer'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'', ''categorical'')) my.data <- laf_to_ffdf(my.data.laf, nrows=1000000) my.data.in.ram <- as.data.frame(my.data)

PD. Comencé a usar el paquete LaF porque me molestaba la lentitud de read.fwf y porque el código PL / SQL PostgreSQL con el que estaba trabajando inicialmente para analizar los datos se estaba convirtiendo en una molestia para mantener.


Sin suficientes detalles sobre sus datos, es difícil dar una respuesta concreta, pero aquí hay algunas ideas para comenzar:

Primero, si está en un sistema Unix, puede obtener información sobre su archivo usando el comando wc . Por ejemplo, wc -l TS_MATRICULA_RS.txt le dirá cuántas líneas hay en su archivo y wc -L TS_MATRICULA_RS.txt informará la longitud de la línea más larga de su archivo. Esto podría ser útil saber. De manera similar, head y tail le permitirían inspeccionar las primeras y últimas 10 líneas de su archivo de texto.

Segundo, algunas sugerencias: Ya que parece que conoce los anchos de cada campo, recomendaría uno de los dos enfoques.

Opción 1: csvkit + su método favorito para leer rápidamente datos grandes

csvkit es un conjunto de herramientas de Python para trabajar con archivos CSV. Una de las herramientas es in2csv , que toma un archivo de formato de ancho fijo combinado con un archivo de "esquema" para crear un CSV adecuado que se pueda usar con otros programas.

El archivo de esquema es, en sí mismo, un archivo CSV con tres columnas: (1) nombre de variable, (2) posición inicial y (3) ancho. Un ejemplo (de la página de manual de in2csv ) es:

column,start,length name,0,30 birthday,30,10 age,40,3

Una vez que haya creado ese archivo, debería poder usar algo como:

in2csv -f fixed -s path/to/schemafile.csv path/to/TS_MATRICULA_RS.txt > TS_MATRICULA_RS.csv

A partir de ahí, sugeriría mirar en la lectura de los datos con la fread de "data.table" o usar sqldf .

Opción 2: sqldf usando substr

El uso de sqldf en un archivo de datos ish grande como el tuyo debería ser bastante rápido, y obtienes la ventaja de poder especificar exactamente lo que quieres leer usando substr .

Nuevamente, esto esperará que tenga un archivo de esquema disponible, como el descrito anteriormente. Una vez que tenga su archivo de esquema, puede hacer lo siguiente:

temp <- read.csv("mySchemaFile.csv") ## Construct your "substr" command GetMe <- paste("select", paste("substr(V1, ", temp$start, ", ", temp$length, ") `", temp$column, "`", sep = "", collapse = ", "), "from fixed", sep = " ") ## Load "sqldf" library(sqldf) ## Connect to your file fixed <- file("TS_MATRICULA_RS.txt") myDF <- sqldf(GetMe, file.format = list(sep = "_"))

Como conoce los anchos, es posible que pueda omitir la generación del archivo de esquema. Desde los anchos, es solo un poco de trabajo con cumsum . Aquí hay un ejemplo básico, read.fwf en el primer ejemplo de read.fwf :

ff <- tempfile() cat(file = ff, "123456", "987654", sep = "/n") read.fwf(ff, widths = c(1, 2, 3)) widths <- c(1, 2, 3) length <- cumsum(widths) start <- length - widths + 1 column <- paste("V", seq_along(length), sep = "") GetMe <- paste("select", paste("substr(V1, ", start, ", ", widths, ") `", column, "`", sep = "", collapse = ", "), "from fixed", sep = " ") library(sqldf) ## Connect to your file fixed <- file(ff) myDF <- sqldf(GetMe, file.format = list(sep = "_")) myDF unlink(ff)