¿Cómo combino 8 archivos CSV (49 millones de filas cada uno) con una columna común y exporto el resultado final a un CSV en una PC Core i7 de 8 GB de RAM?
Mi respuesta instintiva es Miller, un conjunto de herramientas CSV basado en C que es similar a csvkit que Bill Weiner sugirió. Sin embargo, después de generar 8 archivos CSV llamados t1.csv
través de t8.csv
con:
-
serial
+ 20 otras columnas con nombre (ninguna de las cuales tiene el mismo nombre) - 20,000,000 filas (
serial
ejecuta de1
a2
0000000
, todas las demás columnas con números aleatorios) - 2,5 GB de gran tamaño
ni Miller ni csvkit pudieron unir los 8 archivos en mi computadora portátil Core i7 8GB RAM. Ambos masticaron todo mi intercambio de RAM +, mi computadora portátil dejó de responder por un tiempo y el temido asesino OOM de Linux finalmente tipeó ambos cerdos de memoria.
- ¿Más RAM en un teléfono consume más energía?
- ¿Una computadora portátil con procesador Amd A8 6410 con 8 gb de ram es mejor que una computadora portátil con procesador i5 (5a generación) con 4 gb de ram?
- ¿Cuál es la mejor computadora portátil con Windows bajo Rs. 60,000? Tengo un requisito básico de 8 GB de RAM y debería ser ampliable hasta 16 GB.
- Cómo emparejar la RAM correcta con su procesador para lograr el máximo rendimiento
- ¿Puedo usar 2 PC RAM (memoria) con diferentes frecuencias en mi PC?
Esto se debe a que ambos kits de herramientas CSV no hacen suposiciones sobre sus archivos de entrada y, por lo tanto, tienen que hacer una clasificación previa y muchas otras cosas que finalmente terminan leyendo / mapeando archivos completos en la memoria. Obviamente, esto no escala.
Aquí hay un par de alternativas que he probado para que funcionen y admitan CSV mucho más grandes que la RAM disponible:
La solución genérica es importar sus CSV en una base de datos relacional . Es posible que ya esté planeando cargar todos sus CSV en una base de datos para su posterior procesamiento y análisis, y solo necesita deshacerse de un CSV combinado para otros fines.
La mayoría de los DB relacionales tienen opciones para generar resultados SELECT en formato CSV, y SQL le permite, bueno, UNIRSE.
Con SQLite, por ejemplo:
– Importar cada CSV en una tabla separada
.import t1.csv t1
.import t2.csv t2
.import t3.csv t3
.import t4.csv t4
.import t5.csv t5
.import t6.csv t6
.import t7.csv t7
.import t8.csv t8
– Establecer el modo de salida CSV, con encabezados
.mode csv
encabezados en
.output result.csv
– Ahora ÚNETE a todos juntos
SELECCIONAR * DESDE t1
ÚNETE t2 USANDO (serial)
ÚNETE t3 USANDO (serial)
ÚNETE t4 USANDO (serial)
ÚNETE t5 USANDO (serial)
ÚNETE t6 USANDO (serial)
ÚNETE t7 USANDO (serial)
ÚNETE t8 USANDO (serial)
PEDIDO POR SERIE;
No es muy rápido, pero no tiene que preprocesar sus datos de ninguna manera. También puede elegir su método de combinación, que es muy útil cuando algunos valores en su columna común solo aparecen en algunos archivos.
Dado que todos los archivos ya están ordenados en la columna de serie, hay un acceso directo que funciona en todas las plataformas * nix que he visto, un canal de unión:
unirse –header -t, t1.csv t2.csv |
unirse –header -t, – t3.csv |
unirse –header -t, – t4.csv |
unirse –header -t, – t5.csv |
unirse –header -t, – t6.csv |
unirse –header -t, – t7.csv |
unirse a –header -t, – t8.csv> result.csv
Esta es, con mucho, la forma más rápida y eficiente de memoria para hacer esto, pero requiere entradas ordenadas. Además, lo anterior solo genera el equivalente de una unión interna SQL (es decir, la intersección en la columna común en todos los archivos de entrada). Emular otros tipos de unión SQL es sorprendentemente complicado.