para - python and pandas
Marco de datos grande y persistente en pandas (6)
Estoy explorando el cambio a python y pandas como un usuario SAS desde hace mucho tiempo.
Sin embargo, cuando realicé algunas pruebas hoy, me sorprendió que Python se quedara sin memoria cuando intentaba pandas.read_csv()
un archivo pandas.read_csv()
128mb. Tenía aproximadamente 200,000 filas y 200 columnas de datos en su mayoría numéricos.
Con SAS, puedo importar un archivo csv en un conjunto de datos SAS y puede ser tan grande como mi disco duro.
¿Hay algo análogo en pandas
?
Trabajo regularmente con archivos grandes y no tengo acceso a una red informática distribuida.
¡Wes tiene razón, por supuesto! Solo estoy respondiendo para proporcionar un código de ejemplo un poco más completo. Tuve el mismo problema con un archivo de 129 Mb, que fue resuelto por:
from pandas import *
tp = read_csv(''large_dataset.csv'', iterator=True, chunksize=1000) # gives TextFileReader, which is iterable with chunks of 1000 rows.
df = concat(tp, ignore_index=True) # df is DataFrame. If errors, do `list(tp)` instead of `tp`
A continuación está mi flujo de trabajo.
import sqlalchemy as sa
import pandas as pd
import psycopg2
count = 0
con = sa.create_engine(''postgresql://postgres:pwd@localhost:00001/r'')
#con = sa.create_engine(''sqlite:///XXXXX.db'') SQLite
chunks = pd.read_csv(''..file'', chunksize=10000, encoding="ISO-8859-1",
sep='','', error_bad_lines=False, index_col=False, dtype=''unicode'')
Basándose en el tamaño de su archivo, será mejor que optimice el tamaño de archivo.
for chunk in chunks:
chunk.to_sql(name=''Table'', if_exists=''append'', con=con)
count += 1
print(count)
Después de tener todos los datos en la base de datos, puede consultar los que necesita de la base de datos.
En principio, no debería quedarse sin memoria, pero actualmente hay problemas de memoria con read_csv
en archivos grandes causados por algunos problemas internos complejos de Python (esto es vago, pero se conoce desde hace mucho tiempo: http://github.com/pydata/pandas/issues/407 ).
Por el momento no hay una solución perfecta (aquí hay una tediosa: se puede transcribir el archivo fila por fila en una matriz NumPy preasignada o archivo mapeado en np.mmap
), pero es uno que '' Estaré trabajando en un futuro cercano. Otra solución es leer el archivo en partes más pequeñas (use iterator=True, chunksize=1000
) luego concatenar y luego con pd.concat
. El problema aparece cuando extraes todo el archivo de texto en la memoria en un gran sorbo.
Este es un hilo más antiguo, pero solo quería descargar mi solución alternativa aquí. Inicialmente probé el parámetro chunksize
(incluso con valores bastante pequeños como 10000), pero no ayudó mucho; Todavía tenía problemas técnicos con el tamaño de la memoria (mi CSV era ~ 7.5 Gb).
En este momento, simplemente leo trozos de los archivos CSV en un enfoque for-loop y los agrego, por ejemplo, a una base de datos SQLite paso a paso:
import pandas as pd
import sqlite3
from pandas.io import sql
import subprocess
# In and output file paths
in_csv = ''../data/my_large.csv''
out_sqlite = ''../data/my.sqlite''
table_name = ''my_table'' # name for the SQLite database table
chunksize = 100000 # number of lines to process at each iteration
# columns that should be read from the CSV file
columns = [''molecule_id'',''charge'',''db'',''drugsnow'',''hba'',''hbd'',''loc'',''nrb'',''smiles'']
# Get number of lines in the CSV file
nlines = subprocess.check_output(''wc -l %s'' % in_csv, shell=True)
nlines = int(nlines.split()[0])
# connect to database
cnx = sqlite3.connect(out_sqlite)
# Iteratively read CSV and dump lines into the SQLite table
for i in range(0, nlines, chunksize):
df = pd.read_csv(in_csv,
header=None, # no header, define column header manually later
nrows=chunksize, # number of rows to read at each iteration
skiprows=i) # skip rows that were already read
# columns to read
df.columns = columns
sql.to_sql(df,
name=table_name,
con=cnx,
index=False, # don''t use CSV file index
index_label=''molecule_id'', # use a unique column from DataFrame as index
if_exists=''append'')
cnx.close()
Puede usar Pytable en lugar de pandas df. Está diseñado para grandes conjuntos de datos y el formato de archivo está en hdf5. Entonces el tiempo de procesamiento es relativamente rápido.
Si desea cargar grandes archivos csv, dask podría ser una buena opción. Se asemeja a la panda api, por lo que se siente bastante similar a los pandas