Python sin memoria en un archivo CSV grande (numpy)

Tengo un archivo CSV de 3GB que trato de leer con python, necesito la columna mediana.

from numpy import * def data(): return genfromtxt('All.csv',delimiter=',') data = data() # This is where it fails already. med = zeros(len(data[0])) data = data.T for i in xrange(len(data)): m = median(data[i]) med[i] = 1.0/float(m) print med 

El error que me sale es este:

 Python(1545) malloc: *** mmap(size=16777216) failed (error code=12) *** error: can't allocate region *** set a breakpoint in malloc_error_break to debug Traceback (most recent call last): File "Normalize.py", line 40, in  data = data() File "Normalize.py", line 39, in data return genfromtxt('All.csv',delimiter=',') File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site- packages/numpy/lib/npyio.py", line 1495, in genfromtxt for (i, line) in enumerate(itertools.chain([first_line, ], fhd)): MemoryError 

Creo que es solo un error de memoria. Estoy ejecutando un MacOSX de 64 bits con 4 GB de memoria RAM y comstackdos tanto en Pypy como en modo de 64 bits.

¿Cómo puedo solucionar esto? ¿Debo intentar un enfoque distribuido, solo para la gestión de memoria?

Gracias

EDITAR: También probé con esto pero sin suerte …

 genfromtxt('All.csv',delimiter=',', dtype=float16) 

Como otras personas han mencionado, para un archivo muy grande, es mejor iterar.

Sin embargo, comúnmente desea tener todo en memoria por varias razones.

genfromtxt es mucho menos eficiente que loadtxt (aunque maneja los datos faltantes, mientras que loadtxt es más “lean y mean”, por lo que las dos funciones coexisten).

Si sus datos son muy regulares (p. Ej., Solo filas delimitadas simples del mismo tipo), también puede mejorar usando cualquiera de los numpy.fromiter .

Si tiene suficiente ram, considere usar np.loadtxt('yourfile.txt', delimiter=',') (Es posible que también deba especificar skiprows si tiene un encabezado en el archivo).

Como una comparación rápida, la carga de ~ 500 MB de archivo de texto con loadtxt usa ~ 900MB de RAM en uso máximo, mientras que la carga del mismo archivo con genfromtxt usa ~ 2.5GB.

Loadtxt Uso de memoria y CPU de numpy.loadtxt al cargar un archivo ASCII de ~ 500MB


Genfromtxt Uso de memoria y CPU de numpy.genfromtxt al cargar un archivo ASCII de ~ 500MB


Alternativamente, considere algo como lo siguiente. Solo funcionará para datos muy simples y regulares, pero es bastante rápido. ( loadtxt y genfromtxt hacen muchas conjeturas y verificaciones de errores. Si sus datos son muy simples y regulares, puede mejorarlos enormemente).

 import numpy as np def generate_text_file(length=1e6, ncols=20): data = np.random.random((length, ncols)) np.savetxt('large_text_file.csv', data, delimiter=',') def iter_loadtxt(filename, delimiter=',', skiprows=0, dtype=float): def iter_func(): with open(filename, 'r') as infile: for _ in range(skiprows): next(infile) for line in infile: line = line.rstrip().split(delimiter) for item in line: yield dtype(item) iter_loadtxt.rowlength = len(line) data = np.fromiter(iter_func(), dtype=dtype) data = data.reshape((-1, iter_loadtxt.rowlength)) return data #generate_text_file() data = iter_loadtxt('large_text_file.csv') 

Fromiter

Usando fromiter para cargar el mismo archivo de datos de ~ 500MB

El problema con el uso de genfromtxt () es que intenta cargar todo el archivo en la memoria, es decir, en una matriz numpy. Esto es ideal para archivos pequeños pero BAD para entradas de 3GB como la tuya. Como solo está calculando medianas de columna, no es necesario leer todo el archivo. Una forma simple, pero no la más eficiente de hacerlo, sería leer el archivo completo línea por línea varias veces e iterar sobre las columnas.

¿Por qué no estás usando el módulo csv de python?

 >> import csv >> reader = csv.reader(open('All.csv')) >>> for row in reader: ... print row