[python] Pandas의 크고 지속적인 DataFrame

저는 오랜 SAS 사용자로서 파이썬과 판다로의 전환을 모색하고 있습니다.

그러나 오늘 몇 가지 테스트를 실행할 때 pandas.read_csv()128MB csv 파일을 시도 할 때 파이썬의 메모리가 부족하다는 사실에 놀랐습니다 . 약 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. 문제는 전체 텍스트 파일을 한 번의 큰 소리로 메모리로 가져올 때 발생합니다.


답변

물론 Wes가 맞습니다! 좀 더 완전한 예제 코드를 제공하기 위해 차밍하고 있습니다. 129 Mb 파일에서 동일한 문제가 발생하여 다음과 같이 해결되었습니다.

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`


답변

이것은 오래된 스레드이지만 여기에 해결 방법을 덤프하고 싶었습니다. 나는 처음에chunksize 매개 변수를 (10000과 같은 아주 작은 값으로도) 그다지 도움이되지 않았습니다. 메모리 크기에 여전히 기술적 인 문제가있었습니다 (내 CSV는 ~ 7.5Gb였습니다).

지금은 for 루프 접근 방식으로 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가 좋은 옵션 일 수 있습니다. 그것은 pandas api를 모방하므로 pandas와 매우 비슷하게 느껴집니다.

github의 dask에 링크


답변

pandas df 대신 Pytable을 사용할 수 있습니다. 대용량 데이터 세트 용으로 설계되었으며 파일 형식은 hdf5입니다. 따라서 처리 시간이 상대적으로 빠릅니다.


답변