python - chunk - pandas read huge file
¿Cómo dividir la lectura de un archivo csv grande en trozos de tamaño uniforme en Python? (3)
No hay una buena manera de hacer esto para todos los archivos .csv
. Debería poder dividir el archivo en file.seek
utilizando file.seek
para omitir una sección del archivo. Luego, debe escanear un byte a la vez para encontrar el final de la fila. Puede procesar los dos trozos de forma independiente. Algo como el siguiente código (no probado) debería ayudarte a comenzar.
file_one = open(''foo.csv'')
file_two = open(''foo.csv'')
file_two.seek(0, 2) # seek to the end of the file
sz = file_two.tell() # fetch the offset
file_two.seek(sz / 2) # seek back to the middle
chr = ''''
while chr != ''/n'':
chr = file_two.read(1)
# file_two is now positioned at the start of a record
segment_one = csv.reader(file_one)
segment_two = csv.reader(file_two)
No estoy seguro de cómo puede saber que ha terminado de atravesar segment_one
. Si tiene una columna en el CSV que es un identificador de fila, puede detener el procesamiento de segment_one
cuando encuentre el identificador de fila de la primera fila en segment_two
.
En un básico tuve el siguiente proceso.
import csv
reader = csv.reader(open(''huge_file.csv'', ''rb''))
for line in reader:
process_line(line)
Vea esta question relacionada. Quiero enviar la línea de proceso cada 100 filas, para implementar la fragmentación por lotes.
El problema acerca de la implementación de la respuesta relacionada es que el objeto csv no se puede suscribir y no puede usar len.
>>> import csv
>>> reader = csv.reader(open(''dataimport/tests/financial_sample.csv'', ''rb''))
>>> len(reader)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type ''_csv.reader'' has no len()
>>> reader[10:]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: ''_csv.reader'' object is unsubscriptable
>>> reader[10]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: ''_csv.reader'' object is unsubscriptable
¿Como puedo resolver esto?
Podemos usar el módulo pandas para manejar estos grandes archivos csv.
df = pd.DataFrame()
temp = pd.read_csv(''BIG_File.csv'', iterator=True, chunksize=1000)
df = pd.concat(temp, ignore_index=True)
Simplemente haga que su reader
subíndice compaginándolo en una list
. Obviamente, esto se romperá en archivos realmente grandes (ver alternativas en las actualizaciones a continuación):
>>> reader = csv.reader(open(''big.csv'', ''rb''))
>>> lines = list(reader)
>>> print lines[:100]
...
Más información: question
Actualización 1 (versión de lista): Otra forma posible sería simplemente procesar cada mandril, a medida que llega al iterar sobre las líneas:
#!/usr/bin/env python
import csv
reader = csv.reader(open(''4956984.csv'', ''rb''))
chunk, chunksize = [], 100
def process_chunk(chuck):
print len(chuck)
# do something useful ...
for i, line in enumerate(reader):
if (i % chunksize == 0 and i > 0):
process_chunk(chunk)
del chunk[:]
chunk.append(line)
# process the remainder
process_chunk(chunk)
Actualización 2 (versión del generador): no lo he evaluado, pero quizás pueda aumentar el rendimiento utilizando un generador de trozos:
#!/usr/bin/env python
import csv
reader = csv.reader(open(''4956984.csv'', ''rb''))
def gen_chunks(reader, chunksize=100):
"""
Chunk generator. Take a CSV `reader` and yield
`chunksize` sized slices.
"""
chunk = []
for i, line in enumerate(reader):
if (i % chunksize == 0 and i > 0):
yield chunk
del chunk[:]
chunk.append(line)
yield chunk
for chunk in gen_chunks(reader):
print chunk # process chunk
# test gen_chunk on some dummy sequence:
for chunk in gen_chunks(range(10), chunksize=3):
print chunk # process chunk
# => yields
# [0, 1, 2]
# [3, 4, 5]
# [6, 7, 8]
# [9]