Ich versuche, eine große CSV-Datei (ca. 6 GB) in Pandas zu lesen, und ich erhalte den folgenden Speicherfehler:
MemoryError Traceback (most recent call last)
<ipython-input-58-67a72687871b> in <module>()
----> 1 data=pd.read_csv('aphro.csv',sep=';')
C:\Python27\lib\site-packages\pandas\io\parsers.pyc in parser_f(filepath_or_buffer, sep, dialect, compression, doublequote, escapechar, quotechar, quoting, skipinitialspace, lineterminator, header, index_col, names, prefix, skiprows, skipfooter, skip_footer, na_values, na_fvalues, true_values, false_values, delimiter, converters, dtype, usecols, engine, delim_whitespace, as_recarray, na_filter, compact_ints, use_unsigned, low_memory, buffer_lines, warn_bad_lines, error_bad_lines, keep_default_na, thousands, comment, decimal, parse_dates, keep_date_col, dayfirst, date_parser, memory_map, nrows, iterator, chunksize, verbose, encoding, squeeze, mangle_dupe_cols, tupleize_cols, infer_datetime_format)
450 infer_datetime_format=infer_datetime_format)
451
--> 452 return _read(filepath_or_buffer, kwds)
453
454 parser_f.__= name
C:\Python27\lib\site-packages\pandas\io\parsers.pyc in _read(filepath_or_buffer, kwds)
242 return parser
243
--> 244 return parser.read()
245
246 _parser_defaults = {
C:\Python27\lib\site-packages\pandas\io\parsers.pyc in read(self, nrows)
693 raise ValueError('skip_footer not supported for iteration')
694
--> 695 ret = self._engine.read(nrows)
696
697 if self.options.get('as_recarray'):
C:\Python27\lib\site-packages\pandas\io\parsers.pyc in read(self, nrows)
1137
1138 try:
-> 1139 data = self._reader.read(nrows)
1140 except StopIteration:
1141 if nrows is None:
C:\Python27\lib\site-packages\pandas\parser.pyd in pandas.parser.TextReader.read (pandas\parser.c:7145)()
C:\Python27\lib\site-packages\pandas\parser.pyd in pandas.parser.TextReader._read_low_memory (pandas\parser.c:7369)()
C:\Python27\lib\site-packages\pandas\parser.pyd in pandas.parser.TextReader._read_rows (pandas\parser.c:8194)()
C:\Python27\lib\site-packages\pandas\parser.pyd in pandas.parser.TextReader._convert_column_data (pandas\parser.c:9402)()
C:\Python27\lib\site-packages\pandas\parser.pyd in pandas.parser.TextReader._convert_tokens (pandas\parser.c:10057)()
C:\Python27\lib\site-packages\pandas\parser.pyd in pandas.parser.TextReader._convert_with_dtype (pandas\parser.c:10361)()
C:\Python27\lib\site-packages\pandas\parser.pyd in pandas.parser._try_int64 (pandas\parser.c:17806)()
MemoryError:
Hilfe dazu?
Der Fehler zeigt an, dass der Computer nicht über genügend Speicher verfügt, um die gesamte CSV-Datei auf einmal in einen DataFrame einzulesen. Angenommen, Sie benötigen nicht das gesamte Dataset gleichzeitig in Memory. Eine Möglichkeit, das Problem zu vermeiden, besteht darin, CSV in Chunks verarbeiten (durch Angabe des Parameters chunksize
):
chunksize = 10 ** 6
for chunk in pd.read_csv(filename, chunksize=chunksize):
process(chunk)
Der Parameter chucksize
gibt die Anzahl der Zeilen pro Block an . (Der letzte Block kann natürlich weniger als chunksize
Zeilen enthalten.)
Chunking sollte nicht immer die erste Anlaufstelle für dieses Problem sein.
1. Ist die Datei aufgrund wiederholter nicht numerischer Daten oder unerwünschter Spalten groß?
In diesem Fall können Sie manchmal erhebliche Speichereinsparungen durch Einlesen der Spalten als Kategorien und Auswahl der erforderlichen Spalten über den Parameter pd.read_csvusecols
feststellen.
2. Erfordert Ihr Workflow das Schneiden, Manipulieren und Exportieren?
In diesem Fall können Sie dask.dataframe verwenden, um Ihre Berechnungen durchzuführen und iterativ zu exportieren. Das Chunking wird von dask, das auch eine Teilmenge der Pandas-API unterstützt, im Hintergrund ausgeführt.
3. Wenn alles andere fehlschlägt, lesen Sie Zeile für Zeile über Chunks.
Chunk via Pandas oder über csv-Bibliothek als letztes Mittel.
Ich ging so vor:
chunks=pd.read_table('aphro.csv',chunksize=1000000,sep=';',\
names=['lat','long','rf','date','slno'],index_col='slno',\
header=None,parse_dates=['date'])
df=pd.DataFrame()
%time df=pd.concat(chunk.groupby(['lat','long',chunk['date'].map(lambda x: x.year)])['rf'].agg(['sum']) for chunk in chunks)
Für große Daten empfehle ich die Bibliothek "dask"
z.B:
# Dataframes implement the Pandas API
import dask.dataframe as dd
df = dd.read_csv('s3://.../2018-*-*.csv')
Die obige Antwort befriedigt das Thema bereits. Wenn Sie alle Daten im Speicher benötigen, besuchen Sie bcolz . Es komprimiert die Daten im Speicher. Ich habe wirklich gute Erfahrungen damit gemacht. Aber es fehlen viele Pandas
Edit: Ich habe Kompressionsraten von etwa 1/10 oder orig. Fehlende wichtige Merkmale waren Aggregate.
Sie können die Daten als Chunks einlesen und jeden Chunk als Pickle speichern.
import pandas as pd
import pickle
in_path = "" #Path where the large file is
out_path = "" #Path to save the pickle files to
chunk_size = 400000 #size of chunks relies on your available memory
separator = "~"
reader = pd.read_csv(in_path,sep=separator,chunksize=chunk_size,
low_memory=False)
i=1
for chunk in reader:
out_file = out_path + "/data_{}.pkl".format(i)
with open(out_file, "wb") as f:
pickle.dump(chunk,f,pickle.HIGHEST_PROTOCOL)
i+=1
Im nächsten Schritt lesen Sie die Pickles ein und hängen jedes Pickle an Ihren gewünschten Datenrahmen an.
import glob
pickle_path = "" #Same Path as out_path i.e. where the pickle files are
data_p_files=[]
for name in glob.glob(pickle_path + "/data_*.pkl"):
data_p_files.append(name)
df = pd.DataFrame([])
for i in range(len(data_p_files)):
df = df.append(pd.read_pickle(data_p_files[i]),ignore_index=True)
Lösung 1:
Pandas mit großen Daten verwenden
Lösung 2:
TextFileReader = pd.read_csv(path, chunksize=1000) # the number of rows per chunk
dfList = []
for df in TextFileReader:
dfList.append(df)
df = pd.concat(dfList,sort=False)
Die Funktion read_csv und read_table ist fast gleich. Sie müssen jedoch das Trennzeichen "," zuweisen, wenn Sie in Ihrem Programm die Funktion read_table verwenden.
def get_from_action_data(fname, chunk_size=100000):
reader = pd.read_csv(fname, header=0, iterator=True)
chunks = []
loop = True
while loop:
try:
chunk = reader.get_chunk(chunk_size)[["user_id", "type"]]
chunks.append(chunk)
except StopIteration:
loop = False
print("Iteration is stopped")
df_ac = pd.concat(chunks, ignore_index=True)
Sie können sframe versuchen, das dieselbe Syntax wie Pandas hat, aber Sie können Dateien bearbeiten, die größer als Ihr RAM sind.
Hier folgt ein Beispiel:
chunkTemp = []
queryTemp = []
query = pd.DataFrame()
for chunk in pd.read_csv(file, header=0, chunksize=<your_chunksize>, iterator=True, low_memory=False):
#REPLACING BLANK SPACES AT COLUMNS' NAMES FOR SQL OPTIMIZATION
chunk = chunk.rename(columns = {c: c.replace(' ', '') for c in chunk.columns})
#YOU CAN EITHER:
#1)BUFFER THE CHUNKS IN ORDER TO LOAD YOUR WHOLE DATASET
chunkTemp.append(chunk)
#2)DO YOUR PROCESSING OVER A CHUNK AND STORE THE RESULT OF IT
query = chunk[chunk[<column_name>].str.startswith(<some_pattern>)]
#BUFFERING PROCESSED DATA
queryTemp.append(query)
#! NEVER DO pd.concat OR pd.DataFrame() INSIDE A LOOP
print("Database: CONCATENATING CHUNKS INTO A SINGLE DATAFRAME")
chunk = pd.concat(chunkTemp)
print("Database: LOADED")
#CONCATENATING PROCESSED DATA
query = pd.concat(queryTemp)
print(query)
Wenn Sie Pandas verwenden, lesen Sie eine große Datei in einen Block und geben Sie dann Zeile für Zeile nach. Hier ist, was ich getan habe
import pandas as pd
def chunck_generator(filename, header=False,chunk_size = 10 ** 5):
for chunk in pd.read_csv(filename,delimiter=',', iterator=True, chunksize=chunk_size, parse_dates=[1] ):
yield (chunk)
def _generator( filename, header=False,chunk_size = 10 ** 5):
chunk = chunck_generator(filename, header=False,chunk_size = 10 ** 5)
for row in chunk:
yield row
if __== "__main__":
filename = r'file.csv'
generator = generator(filename=filename)
while True:
print(next(generator))
Zusätzlich zu den obigen Antworten ist d6tstack für diejenigen, die CSV verarbeiten und anschließend in CSV, Parkett oder SQL exportieren möchten, eine gute Option. Sie können mehrere Dateien laden und befasst sich mit Änderungen des Datenschemas (hinzugefügte/entfernte Spalten). Chunked Out-Core-Unterstützung ist bereits eingebaut.
def apply(dfg):
# do stuff
return dfg
c = d6tstack.combine_csv.CombinerCSV([bigfile.csv], apply_after_read=apply, sep=',', chunksize=1e6)
# or
c = d6tstack.combine_csv.CombinerCSV(glob.glob('*.csv'), apply_after_read=apply, chunksize=1e6)
# output to various formats, automatically chunked to reduce memory consumption
c.to_csv_combine(filename='out.csv')
c.to_parquet_combine(filename='out.pq')
c.to_psql_combine('postgresql+psycopg2://usr:[email protected]/db', 'tablename') # fast for postgres
c.to_mysql_combine('mysql+mysqlconnector://usr:[email protected]/db', 'tablename') # fast for mysql
c.to_sql_combine('postgresql+psycopg2://usr:[email protected]/db', 'tablename') # slow but flexible
Für den Fall, dass noch jemand so etwas sucht, habe ich festgestellt, dass diese neue Bibliothek mit dem Namen modin helfen kann. Es verwendet verteiltes Computing, das beim Lesen helfen kann. Hier ist ein Nizza Artikel der seine Funktionalität mit Pandas vergleicht. Es verwendet im Wesentlichen die gleichen Funktionen wie Pandas.
import modin.pandas as pd
pd.read_csv(CSV_FILE_NAME)