developer tip

Pandas의 크고 지속적인 DataFrame

optionbox 2020. 9. 9. 07:55
반응형

Pandas의 크고 지속적인 DataFrame


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

그러나 오늘 몇 가지 테스트를 실행할 때 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 파일에서 동일한 문제가 발생했으며 다음과 같은 방법으로 해결되었습니다.

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.5Gb였습니다).

지금은 for-loop 접근 방식으로 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에 링크


You can use Pytable rather than pandas df. It is designed for large data sets and the file format is in hdf5. So the processing time is relatively fast.

참고URL : https://stackoverflow.com/questions/11622652/large-persistent-dataframe-in-pandas

반응형