Tengo tablas muy grandes (30 millones de filas) que me gustaría cargar como marcos de datos en R. read.table()
tiene muchas características convenientes, pero parece que hay mucha lógica en la implementación que ralentizaría las cosas. En mi caso, supongo que conozco los tipos de columnas con anticipación, la tabla no contiene ningún encabezado de columna o nombre de fila, y no tiene caracteres patológicos de los que deba preocuparme.
Sé que leer en una tabla como una lista usando scan()
puede ser bastante rápido, por ejemplo:
datalist <- scan('myfile',sep='\t',list(url='',popularity=0,mintime=0,maxtime=0)))
Pero algunos de mis intentos de convertir esto en un marco de datos parecen disminuir el rendimiento de lo anterior en un factor de 6:
df <- as.data.frame(scan('myfile',sep='\t',list(url='',popularity=0,mintime=0,maxtime=0))))
¿Hay una mejor manera de hacer esto? ¿O posiblemente un enfoque completamente diferente del problema?
feather
. Para leer datosfeather
es mucho más rápido quefread
. Por ejemplo, en un conjunto de datos de 4GB que acabo de cargarread_feather
fue aproximadamente 4.5 veces más rápido quefread
. Para guardar datosfwrite
es aún más rápido. blog.dominodatalab.com/the-r-data-io-shootoutfeather
lo tanto, es más rápido para leer, pero utiliza mucho más espacio de almacenamiento.feather
es una buena opción. Si solo le importa poder leer sus datos en R,rds
es preferible.Aquí hay un ejemplo que utiliza
fread
desdedata.table
1.8.7Los ejemplos provienen de la página de ayuda
fread
, con los tiempos en mi Windows XP Core 2 duo E8400.tabla de lectura estándar
read.table optimizado
fread
sqldf
ff / ffdf
En resumen:
fuente
fread
. Había intentado leerlo con las funciones básicas de R y me llevó unas 15 horas.readr
?fread
tiene algunos competidores reales, podría ser útil agregar puntos de referencia para unfread
uso optimizado , especificandocolClasses
, etc.No vi esta pregunta inicialmente y formulé una pregunta similar unos días después. Voy a tomar mi pregunta anterior, pero pensé agregar una respuesta aquí para explicar cómo solía
sqldf()
hacer esto.Se ha debatido poco sobre la mejor manera de importar 2 GB o más de datos de texto en un marco de datos R. Ayer escribí una publicación de blog sobre el uso
sqldf()
para importar los datos a SQLite como un área de ensayo, y luego succionarlos de SQLite a R. Esto funciona muy bien para mí. Pude obtener 2 GB (3 columnas, filas de 40 mm) de datos en <5 minutos. Por el contrario, elread.csv
comando se ejecutó toda la noche y nunca se completó.Aquí está mi código de prueba:
Configure los datos de prueba:
Reinicié R antes de ejecutar la siguiente rutina de importación:
Dejé correr la siguiente línea toda la noche pero nunca se completó:
fuente
Curiosamente, nadie respondió la parte inferior de la pregunta durante años a pesar de que esta es una lista importante con
data.frame
simplemente los atributos correctos, por lo que si tiene datos grandes que no desea usaras.data.frame
o similares para una lista. Es mucho más rápido simplemente "convertir" una lista en un marco de datos in situ:Esto no hace una copia de los datos, por lo que es inmediato (a diferencia de todos los demás métodos). Se supone que ya ha establecido
names()
en la lista en consecuencia.[En cuanto a la carga de datos grandes en R, personalmente, los vuelco por columna en archivos binarios y los uso
readBin()
, ese es, con mucho, el método más rápido (aparte de mmapping) y solo está limitado por la velocidad del disco. Analizar archivos ASCII es inherentemente lento (incluso en C) en comparación con los datos binarios.]fuente
tracmem
sugiere esoattr<-
yclass<-
hacer copias internamente.bit::setattr
odata.table::setattr
no lo hará.df=scan(...); names(df)=...; attr...; class...
- veatracemem()
(probado en R 2.15.2)Esto se preguntó anteriormente en R-Help , por lo que vale la pena revisarlo.
Una sugerencia fue usar
readChar()
y luego manipular cadenas en el resultado constrsplit()
ysubstr()
. Puede ver que la lógica involucrada en readChar es mucho menor que read.table.No sé si la memoria es un problema aquí, pero es posible que también desee echar un vistazo al paquete HadoopStreaming . Esto usa Hadoop , que es un marco de MapReduce diseñado para manejar grandes conjuntos de datos. Para esto, usaría la función hsTableReader. Este es un ejemplo (pero tiene una curva de aprendizaje para aprender Hadoop):
La idea básica aquí es dividir la importación de datos en fragmentos. Incluso podría ir tan lejos como para usar uno de los marcos paralelos (por ejemplo, nieve) y ejecutar la importación de datos en paralelo segmentando el archivo, pero lo más probable es que para conjuntos de datos grandes que no ayuden, ya que se encontrará con restricciones de memoria, Es por eso que map-reduce es un mejor enfoque.
fuente
Una alternativa es usar el
vroom
paquete. Ahora en CRAN.vroom
no carga todo el archivo, indexa dónde se encuentra cada registro y se lee más tarde cuando lo usa.Consulte Introducción a vroom , Comience con vroom y los puntos de referencia de vroom .
La descripción básica es que la lectura inicial de un archivo enorme será mucho más rápida y las modificaciones posteriores a los datos pueden ser un poco más lentas. Entonces, dependiendo de cuál sea su uso, podría ser la mejor opción.
Vea un ejemplo simplificado de los puntos de referencia de vroom a continuación, las partes clave para ver son los tiempos de lectura súper rápidos, pero las operaciones ligeramente más reducidas como el agregado, etc.
fuente
Unos puntos adicionales menores que vale la pena mencionar. Si tiene un archivo muy grande, puede calcular sobre la marcha el número de filas (si no hay encabezado) usando (donde
bedGraph
está el nombre de su archivo en su directorio de trabajo):A continuación, puede utilizar ya sea en que
read.csv
,read.table
...fuente
Muchas veces creo que es una buena práctica mantener bases de datos más grandes dentro de una base de datos (por ejemplo, Postgres). No uso nada mucho más grande que (nrow * ncol) ncell = 10M, que es bastante pequeño; pero a menudo encuentro que quiero que R cree y contenga gráficos intensivos en memoria solo mientras realizo consultas desde múltiples bases de datos. En el futuro de las computadoras portátiles de 32 GB, algunos de estos tipos de problemas de memoria desaparecerán. Pero el atractivo de usar una base de datos para contener los datos y luego usar la memoria de R para los resultados de la consulta y los gráficos resultantes aún puede ser útil. Algunas ventajas son:
(1) Los datos permanecen cargados en su base de datos. Simplemente vuelva a conectar en pgadmin a las bases de datos que desee cuando vuelva a encender su computadora portátil.
(2) Es cierto que R puede realizar muchas más operaciones estadísticas y gráficas ingeniosas que SQL. Pero creo que SQL está mejor diseñado para consultar grandes cantidades de datos que R.
fuente
Estoy leyendo datos muy rápidamente usando el nuevo
arrow
paquete. Parece estar en una etapa bastante temprana.Específicamente, estoy usando el formato columnar de parquet . Esto convierte de nuevo a a
data.frame
en R, pero puede obtener aceleraciones aún más profundas si no lo hace. Este formato es conveniente ya que también se puede usar desde Python.Mi principal caso de uso para esto es en un servidor RShiny bastante restringido. Por estas razones, prefiero mantener los datos adjuntos a las aplicaciones (es decir, fuera de SQL) y, por lo tanto, requieren un tamaño de archivo pequeño y velocidad.
Este artículo vinculado proporciona evaluaciones comparativas y una buena descripción general. He citado algunos puntos interesantes a continuación.
https://ursalabs.org/blog/2019-10-columnar-perf/
Tamaño del archivo
Velocidad de lectura
Prueba independiente
Realicé algunas evaluaciones comparativas independientes en un conjunto de datos simulado de 1,000,000 de filas. Básicamente barajé un montón de cosas para intentar desafiar la compresión. También agregué un campo de texto corto de palabras aleatorias y dos factores simulados.
Datos
Lee y escribe
Escribir los datos es fácil.
Leer los datos también es fácil.
Probé la lectura de estos datos con algunas de las opciones de la competencia, y obtuve resultados ligeramente diferentes a los del artículo anterior, que es de esperar.
Este archivo no es tan grande como el artículo de referencia, así que tal vez esa sea la diferencia.
Pruebas
as_data_frame = FALSE
)arrow
)feather
)Observaciones
Para este archivo en particular, en
fread
realidad es muy rápido. Me gusta el pequeño tamaño de archivo de laparquet2
prueba altamente comprimida . Puedo invertir el tiempo para trabajar con el formato de datos nativo en lugar dedata.frame
si realmente necesito acelerar.Aquí
fst
también hay una gran opción. Usaría elfst
formato altamente comprimido o el altamente comprimidoparquet
dependiendo de si necesitaba la velocidad o el tamaño del archivo.fuente
En lugar de la read.table convencional, creo que fread es una función más rápida. Especificar atributos adicionales como seleccionar solo las columnas requeridas, especificar colclasses y cadenas como factores reducirá el tiempo necesario para importar el archivo.
fuente
He intentado todo lo anterior y [readr] [1] hizo el mejor trabajo. Solo tengo 8 gb de RAM
Bucle para 20 archivos, 5 gb cada uno, 7 columnas:
fuente