Я изучаю возможность перехода на python и pandas как давний пользователь SAS.
Однако при выполнении некоторых тестов сегодня я был удивлен, что python исчерпал память при попытке pandas.read_csv()
создать csv-файл размером 128 МБ. В нем было около 200 000 строк и 200 столбцов, в основном числовых данных.
С помощью SAS я могу импортировать CSV-файл в набор данных SAS, и он может быть размером с мой жесткий диск.
Есть что-то аналогичное в pandas
?
Я регулярно работаю с большими файлами и не имею доступа к распределенной вычислительной сети.
Ответы:
В принципе, не должно быть нехватки памяти, но в настоящее время существуют проблемы с памятью
read_csv
для больших файлов, вызванные некоторыми сложными внутренними проблемами Python (это расплывчато, но известно уже давно: http://github.com/pydata / pandas / issues / 407 ).На данный момент нет идеального решения (вот утомительное: вы могли бы построчно транскрибировать файл в заранее выделенный массив NumPy или файл с отображением памяти -
np.mmap
), но над ним я буду работать в ближайшее время. Другое решение - читать файл более мелкими частями (использоватьiterator=True, chunksize=1000
), а затем объединять их сpd.concat
. Проблема возникает, когда вы помещаете весь текстовый файл в память одним большим куском.источник
Уэс, конечно, прав! Я просто пытаюсь предоставить более полный пример кода. У меня была такая же проблема с файлом 129 Мб, которую решили:
import pandas as pd tp = pd.read_csv('large_dataset.csv', iterator=True, chunksize=1000) # gives TextFileReader, which is iterable with chunks of 1000 rows. df = pd.concat(tp, ignore_index=True) # df is DataFrame. If errors, do `list(tp)` instead of `tp`
источник
df = concate(tp, ignore_index=True)
?AssertionError: first argument must be a list-like of pandas objects, you passed an object of type "TextFileReader"
. Есть идеи, что здесь происходит?pd.concat(list(tp), ignore_index=True)
Это старый поток, но я просто хотел сбросить здесь свое обходное решение. Сначала я попробовал
chunksize
параметр (даже с довольно маленькими значениями, например 10000), но это не сильно помогло; остались технические проблемы с объемом памяти (мой CSV был ~ 7,5 Гб).Прямо сейчас я просто читаю куски CSV-файлов в цикле for и добавляю их, например, в базу данных SQLite шаг за шагом:
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()
источник
pandas.read_csv
напрямую возвращает (по крайней мере, в той версии, которую я использую сейчас) итератор, если вы просто предоставитеiterator=True
иchunksize=chunksize
. Следовательно, вы просто выполняетеfor
цикл поpd.read_csv
вызову вместо того, чтобы каждый раз повторно создавать его экземпляр. Однако это стоит только накладных расходов на вызовы, возможно, нет значительного влияния.iterator=True
и тогдаchunksize
уже существовали, если я правильно помню. Возможно, в более старой версии была ошибка, которая вызвала взрыв памяти - я попробую еще раз, когда в следующий раз прочитаю большой DataFrame в Pandas (сейчас я в основном использую Blaze для таких задач)Ниже мой рабочий процесс.
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')
Исходя из размера вашего файла, вам лучше оптимизировать chunksize.
for chunk in chunks: chunk.to_sql(name='Table', if_exists='append', con=con) count += 1 print(count)
После того, как все данные будут в базе данных, вы можете запросить нужные из базы данных.
источник
Если вы хотите загружать огромные файлы csv, dask может быть хорошим вариантом. Он имитирует api pandas, поэтому очень похож на pandas
ссылка на dask на github
источник
Вы можете использовать Pytable, а не pandas df. Он предназначен для больших наборов данных, а формат файла - hdf5. Таким образом, время обработки относительно невелико.
источник