Большой, постоянный DataFrame в пандах

Я изучаю возможность перехода на python и pandas как давний пользователь SAS.

Однако, выполняя некоторые тесты сегодня, я был удивлен, что питону не хватило памяти при попытке 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 Мб, которая была решена с помощью:

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 Гб).

Прямо сейчас я просто читаю фрагменты CSV-файлов в циклическом подходе и постепенно добавляю их, например, в базу данных 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()    

Ниже мой рабочий поток.

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)

После того, как все данные в базе данных, вы можете запросить те, которые вам нужны из базы данных.

Если вы хотите загружать огромные CSV-файлы, хорошим вариантом может быть dask. Он имитирует панды API, поэтому он очень похож на панд

ссылка на dask на github

Вы можете использовать Pytable вместо Pandas DF. Он предназначен для больших массивов данных, а формат файла - hdf5. Таким образом, время обработки относительно быстро.

Другие вопросы по тегам