Большой, постоянный фрейм данных в панд
Я изучаю переход на python и pandas как давний пользователь SAS.
однако, при запуске некоторых тестов сегодня, я был удивлен, что python выбежал из памяти при попытке pandas.read_csv()
файл 128 Мб в формате CSV. Он имел около 200 000 строк и 200 столбцов в основном числовые данные.
С помощью SAS я могу импортировать csv-файл в набор данных SAS, и он может быть размером с мой жесткий диск.
есть ли что-то аналогичное в pandas
?
Я регулярно работа с большими файлами и не имеют доступа к распределенной вычислительной сети.
6 ответов:
в принципе он не должен работать из памяти, но в настоящее время есть проблемы с памятью с
read_csv
на больших файлах, вызванных некоторыми сложными внутренними проблемами Python (это расплывчато, но это было известно в течение длительного времени:http://github.com/pydata/pandas/issues/407).на данный момент нет идеального решения (вот утомительное: вы можете транскрибировать файл по строкам в предварительно выделенный массив NumPy или файл с отображением памяти -
np.mmap
), но это один я буду работаем над этим в ближайшее время. Другим решением является чтение файла в меньших частях (используйтеiterator=True, chunksize=1000
) то сцепить затем сpd.concat
. Проблема возникает, когда вы вытаскиваете весь текстовый файл в память одним большим глотком.
Уэс, конечно, правы! Я просто подхожу, чтобы предоставить немного более полный пример кода. У меня была та же проблема с файлом 129 Mb, которая была решена с помощью:
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`
это более старый поток, но я просто хотел сбросить свое обходное решение здесь. Я изначально пробовал
chunksize
параметр (даже с довольно маленькими значениями, такими как 10000), но это не очень помогло; все еще были технические проблемы с размером памяти (мой CSV был ~ 7.5 Gb).прямо сейчас я просто читаю куски CSV-файлов в подходе for-loop и добавляю их, например, в базу данных 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()
Если вы хотите загрузить огромные файлы csv, dask может быть хорошим вариантом. Он имитирует api pandas, поэтому он очень похож на pandas
ниже мой рабочий поток.
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')
основываясь на вашем размере файла, вам лучше оптимизировать размер куска.
for chunk in chunks: chunk.to_sql(name='Table', if_exists='append', con=con) count += 1 print(count)
после того, как все данные в базе данных, вы можете запросить те, которые вам нужны из базы данных.