Estoy tratando de hacer algo bastante simple, leer un archivo csv grande en un marco de datos de pandas.
data = pandas.read_csv(filepath, header = 0, sep = DELIMITER,skiprows = 2)
El código falla con a MemoryError
, o simplemente nunca termina.
El uso de memoria en el administrador de tareas se detuvo en 506 Mb y después de 5 minutos sin cambios y sin actividad de CPU en el proceso lo detuve.
Estoy usando pandas versión 0.11.0.
Soy consciente de que solía haber un problema de memoria con el analizador de archivos, pero según http://wesmckinney.com/blog/?p=543 esto debería haberse solucionado.
El archivo que estoy tratando de leer es de 366 Mb, el código de arriba funciona si corto el archivo a algo corto (25 Mb).
También ha sucedido que aparece una ventana emergente que me dice que no puede escribir en la dirección 0x1e0baf93 ...
Stacktrace:
Traceback (most recent call last):
File "F:\QA ALM\Python\new WIM data\new WIM data\new_WIM_data.py", line 25, in
<module>
wimdata = pandas.read_csv(filepath, header = 0, sep = DELIMITER,skiprows = 2
)
File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\io\parsers.py"
, line 401, in parser_f
return _read(filepath_or_buffer, kwds)
File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\io\parsers.py"
, line 216, in _read
return parser.read()
File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\io\parsers.py"
, line 643, in read
df = DataFrame(col_dict, columns=columns, index=index)
File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\frame.py"
, line 394, in __init__
mgr = self._init_dict(data, index, columns, dtype=dtype)
File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\frame.py"
, line 525, in _init_dict
dtype=dtype)
File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\frame.py"
, line 5338, in _arrays_to_mgr
return create_block_manager_from_arrays(arrays, arr_names, axes)
File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\internals
.py", line 1820, in create_block_manager_from_arrays
blocks = form_blocks(arrays, names, axes)
File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\internals
.py", line 1872, in form_blocks
float_blocks = _multi_blockify(float_items, items)
File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\internals
.py", line 1930, in _multi_blockify
block_items, values = _stack_arrays(list(tup_block), ref_items, dtype)
File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\internals
.py", line 1962, in _stack_arrays
stacked = np.empty(shape, dtype=dtype)
MemoryError
Press any key to continue . . .
Un poco de antecedentes: estoy tratando de convencer a la gente de que Python puede hacer lo mismo que R. Para esto, estoy tratando de replicar un script R que
data <- read.table(paste(INPUTDIR,config[i,]$TOEXTRACT,sep=""), HASHEADER, DELIMITER,skip=2,fill=TRUE)
R no solo logra leer bien el archivo anterior, sino que incluso lee varios de estos archivos en un bucle for (y luego hace algunas cosas con los datos). Si Python tiene un problema con archivos de ese tamaño, podría estar librando una batalla perdida ...
nrows=something small
aread_csv
para asegurarse de que no sea del tamaño del archivo lo que causa problemas, lo que, como dijo Andy, no debería ser el caso.csv_chunks = pandas.read_csv(filepath, sep = DELIMITER,skiprows = 1, chunksize = 10000)
, luego concatenar los fragmentosdf = pandas.concat(chunk for chunk in csv_chunks)
. Todavía estoy interesado en saber por qué leerlo de una vez no funciona, para mí esto parece un problema con el lector de csv.chunksize=1000
truco para leer el csv, y luego trato de concatenar todos los fragmentos en un gran marco de datos, es en este punto que la memoria explota, con aproximadamente 3-4 veces una huella de memoria en comparación con el tamaño del archivo original. ¿Alguien tiene una idea de por qué podría explotar el marco de datos?Respuestas:
Limitación de memoria de Windows
Los errores de memoria ocurren mucho con Python cuando se usa la versión de 32 bits en Windows. Esto se debe a que los procesos de 32 bits solo obtienen 2 GB de memoria para jugar de forma predeterminada.
Trucos para reducir el uso de memoria
Si no está utilizando Python de 32 bits en Windows, pero está buscando mejorar la eficiencia de su memoria mientras lee archivos csv, hay un truco.
La función pandas.read_csv toma una opción llamada
dtype
. Esto le permite a los pandas saber qué tipos existen dentro de sus datos csv.Como funciona esto
Por defecto, los pandas intentarán adivinar qué tipo de dtipos tiene su archivo csv. Esta es una operación muy pesada porque mientras está determinando el tipo d, tiene que mantener todos los datos sin procesar como objetos (cadenas) en la memoria.
Ejemplo
Digamos que su csv se ve así:
name, age, birthday Alice, 30, 1985-01-01 Bob, 35, 1980-01-01 Charlie, 25, 1990-01-01
Por supuesto, este ejemplo no es un problema para leerlo en la memoria, pero es solo un ejemplo.
Si los pandas leyeran el archivo csv anterior sin ninguna opción dtype, la edad se almacenaría como cadenas en la memoria hasta que los pandas hayan leído suficientes líneas del archivo csv para hacer una suposición calificada.
Creo que lo predeterminado en pandas es leer 1,000,000 filas antes de adivinar el tipo d.
Solución
Al especificar
dtype={'age':int}
como una opción a la.read_csv()
voluntad, los pandas saben que la edad debe interpretarse como un número. Esto le ahorra mucha memoria.Problema con datos corruptos
Sin embargo, si su archivo csv estuviera dañado, así:
name, age, birthday Alice, 30, 1985-01-01 Bob, 35, 1980-01-01 Charlie, 25, 1990-01-01 Dennis, 40+, None-Ur-Bz
Luego, especificar
dtype={'age':int}
romperá el.read_csv()
comando, porque no se puede convertir"40+"
a int. ¡Así que desinfecta tus datos con cuidado!Aquí puede ver cómo el uso de memoria de un marco de datos de pandas es mucho mayor cuando los flotantes se mantienen como cadenas:
Inténtalo tú mismo
df = pd.DataFrame(pd.np.random.choice(['1.0', '0.6666667', '150000.1'],(100000, 10))) resource.getrusage(resource.RUSAGE_SELF).ru_maxrss # 224544 (~224 MB) df = pd.DataFrame(pd.np.random.choice([1.0, 0.6666667, 150000.1],(100000, 10))) resource.getrusage(resource.RUSAGE_SELF).ru_maxrss # 79560 (~79 MB)
fuente
read_csv
función esté haciendo algo increíblemente extraño, me sorprendería mucho si el uso de memoria fuera notablemente mayor.Tuve el mismo problema de memoria con una simple lectura de un archivo de texto delimitado por tabulaciones de aproximadamente 1 GB de tamaño (más de 5,5 millones de registros) y esto resolvió el problema de memoria:
df = pd.read_csv(myfile,sep='\t') # didn't work, memory error df = pd.read_csv(myfile,sep='\t',low_memory=False) # worked fine and in less than 30 seconds
Spyder 3.2.3 Python 2.7.13 64 bits
fuente
low_memory=False
Utilizo Pandas en mi caja de Linux y enfrenté muchas fugas de memoria que solo se resolvieron después de actualizar Pandas a la última versión después de clonarlo desde github.
fuente
También encontré este problema cuando estaba ejecutando en una máquina virtual, o en algún otro lugar donde la memoria es estrictamente limitada. No tiene nada que ver con pandas o numpy o csv, pero siempre sucederá si intenta usar más memoria como puede usar, ni siquiera solo en python.
La única oportunidad que tienes es lo que ya has intentado, trata de cortar lo grande en pedazos más pequeños que encajen en la memoria.
Si alguna vez se preguntó de qué se trata MapReduce, lo descubrió por sí mismo ... MapReduce intentaría distribuir los fragmentos en muchas máquinas, trataría de procesar el fragmento en una máquina una tras otra.
Lo que descubrió con la concatenación de los archivos fragmentados podría ser un problema, tal vez se necesite alguna copia en esta operación ... pero al final esto tal vez lo salve en su situación actual, pero si su csv se vuelve un poco más grande podrías correr contra esa pared de nuevo ...
También podría ser que pandas sea tan inteligente que en realidad solo cargue los fragmentos de datos individuales en la memoria si hace algo con ellos, como concatenar a un gran df.
Varias cosas que puedes probar:
fuente
No hay ningún error para Pandas 0.12.0 y NumPy 1.8.0.
Me las arreglé para crear un DataFrame grande y guardarlo en un archivo csv y luego leerlo con éxito. Por favor, vea el ejemplo aquí. . El tamaño del archivo es 554 Mb (incluso funcionó para archivos de 1.1 Gb, tomó más tiempo, generar una frecuencia de uso de archivos de 1.1Gb de 30 segundos). Aunque tengo 4Gb de RAM disponibles.
Mi sugerencia es intentar actualizar Pandas. Otra cosa que podría ser útil es intentar ejecutar su script desde la línea de comandos, porque para R no está usando Visual Studio (esto ya se sugirió en los comentarios a su pregunta), por lo tanto, tiene más recursos disponibles.
fuente
Lo intenté
chunksize
mientras leía un archivo CSV grandereader = pd.read_csv(filePath,chunksize=1000000,low_memory=False,header=0)
La lectura es ahora la lista. Podemos iterar
reader
y escribir / agregar al nuevo csv o podemos realizar cualquier operaciónfor chunk in reader: print(newChunk.columns) print("Chunk -> File process") with open(destination, 'a') as f: newChunk.to_csv(f, header=False,sep='\t',index=False) print("Chunk appended to the file")
fuente
Agregue estos: ratings = pd.read_csv (..., low_memory = False, memory_map = True )
Mi memoria con estos dos: # 319.082.496 Sin estos dos: # 349.110.272
fuente
Aunque esta es una solución alternativa, no tanto como una solución, intentaría convertir ese CSV a JSON (debería ser trivial) y usar el
read_json
método en su lugar: he estado escribiendo y leyendo JSON / marcos de datos considerables (cientos de MB) en Pandas esto manera sin ningún problema en absoluto.fuente