Большой, постоянный DataFrame в pandas

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

Однако при запуске некоторых тестов сегодня я был удивлен, что на python закончилась нехватка памяти при попытке pandas.read_csv() файла csv размером 128 МБ. Он имел около 200 000 строк и 200 столбцов в основном числовых данных.

С помощью SAS я могу импортировать CSV файл в набор данных SAS, и он может быть размером с мой жесткий диск.

Есть ли что-то аналогичное в pandas?

Я регулярно работаю с большими файлами и не имею доступа к распределенной вычислительной сети.

Ответ 1

В принципе, он не должен заканчиваться из памяти, но в настоящее время проблемы с памятью с read_csv на больших файлах возникают из-за некоторых сложных внутренних проблем Python (это неопределенно, но оно известно давно: http://github.com/pydata/pandas/issues/407).

В настоящее время нет идеального решения (здесь утомительно: вы можете транскрибировать файл по строкам в предварительно выделенный массив NumPy или файл с отображением памяти - np.mmap), но он один, над которым я буду работать в ближайшем будущем. Другое решение состоит в том, чтобы прочитать файл меньшими частями (используйте iterator=True, chunksize=1000), затем конкатенируйте с помощью pd.concat. Проблема возникает, когда вы вытаскиваете весь текстовый файл в память одним большим slurp.

Ответ 2

Уес, конечно, прав! Я просто подшучиваю, чтобы предоставить более полный примерный код. У меня была та же проблема с файлом размером 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`

Ответ 3

Это старый поток, но я просто хотел сбросить свое решение для решения проблемы. Сначала я попробовал параметр 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()    

Ответ 4

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

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

Ответ 5

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

Ответ 6

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

import sqlalchemy as sa
import pandas as pd
import psycopg2

count = 0
con = sa.create_engine('postgresql://postgres:[email protected]: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)

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