Pandas의 크고 지속적인 DataFrame


93

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

그러나 오늘 몇 가지 테스트를 실행할 때 pandas.read_csv()128MB csv 파일을 시도 할 때 파이썬의 메모리가 부족하다는 사실에 놀랐습니다 . 약 200,000 개의 행과 200 개의 열이 주로 숫자 데이터로 구성되었습니다.

SAS를 사용하면 csv 파일을 SAS 데이터 세트로 가져올 수 있으며 내 하드 드라이브만큼 커질 수 있습니다.

비슷한 것이 있습니까? pandas 있습니까?

저는 정기적으로 대용량 파일로 작업하고 분산 컴퓨팅 네트워크에 액세스 할 수 없습니다.


나는 pandas에 익숙하지 않지만 파일을 반복하여 살펴보고 싶을 수도 있습니다. pandas.pydata.org/pandas-docs/stable/...
— monkut

답변:


80

원칙적으로 메모리가 부족하면 안되지만 현재는 read_csv복잡한 Python 내부 문제로 인해 대용량 파일에 메모리 문제가 있습니다 (모호하지만 오랫동안 알려져 왔습니다 : http://github.com/pydata). / pandas / issues / 407 ).

현재 완벽한 솔루션은 없습니다 (여기에 지루한 솔루션이 있습니다 : 파일을 행 단위로 미리 할당 된 NumPy 배열 또는 메모리 매핑 된 파일로 변환 np.mmap할 수 있습니다-). 가까운 장래에. 또 다른 해결책은 파일을 더 작은 조각으로 읽은 iterator=True, chunksize=1000다음 (사용 ) pd.concat. 문제는 전체 텍스트 파일을 한 번의 큰 소리로 메모리로 가져올 때 발생합니다.


1
파일을 읽고 모두를 하나의 DataFrame으로 연결할 수 있다고 가정합니다. DataFrame이 메모리에 있어야합니까? SAS를 사용하면 하드 드라이브 공간이있는 한 모든 크기의 데이터 세트로 작업 할 수 있습니다. DataFrames와 동일합니까? 나는 그들이 하드 드라이브 공간이 아닌 RAM에 의해 제한된다는 인상을 받았습니다. 멍청한 질문에 대해 죄송하고 도움을 주셔서 감사합니다. 나는 당신의 책을 즐기고 있습니다.
— Zelazny7 2012

3
맞습니다, 당신은 RAM의 제약을받습니다. SAS는 실제로 "코어 외부"빅 데이터 처리를 훨씬 더 잘 지원합니다.
— Wes McKinney

5
@WesMcKinney 0.10에 착륙 한 새로운 csv 로더 때문에 이러한 해결 방법은 더 이상 필요하지 않습니다.
— 가브리엘 그랜트

81

물론 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`

6
나는 당신이 할 수 있다고 생각합니까 df = concate(tp, ignore_index=True)?
— Andy Hayden

@smci x4 (550Mb) 또는 x8 (1.1Gb) 반복되는 동일한 데이터로 빠르게 시도했습니다. 흥미롭게도 [x for x in tp]의 유무에 관계없이 x4는 잘 진행되었고 x8은 MemoryError에서 충돌했습니다.
— fickludd

3
사용하는 동안이 오류가 발생합니다 : AssertionError: first argument must be a list-like of pandas objects, you passed an object of type "TextFileReader". 여기서 무슨 일이 일어나고 있는지 아십니까?
— Prince Kumar

3
이 버그는 0.14 (곧 출시)에서 수정 될 것입니다 . github.com/pydata/pandas/pull/6941 ; 0.14.0 <에 대한 해결 방법은하는 것입니다pd.concat(list(tp), ignore_index=True)
— 제프

1
값이 문자열이거나 범주 형이면 어떻게
— 됩니까

41

이것은 오래된 스레드이지만 여기에 해결 방법을 덤프하고 싶었습니다. 나는 처음에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()    

4
청크 읽기 기능의 실제 사용 사례를 보는 데 매우 유용합니다. 감사.
— Alex Kestner 2015-06-30

5
이 오래된 주제에 대한 작은 pandas.read_csv말입니다 . 단순히 iterator=Trueand 를 제공하면 반복자를 (적어도 현재 사용중인 버전에서) 직접 반환합니다 chunksize=chunksize. 따라서 매번 다시 인스턴스화하는 대신 호출에 대해 for루프를 수행합니다 pd.read_csv. 그러나 이는 호출 오버 헤드 만 발생하며 큰 영향은 없을 수 있습니다.
— Joël 2015

1
안녕, 조엘. 메모 감사합니다! iterator=True와 chunksize내가 정확히 기억한다면 매개 변수는 이미 다시 존재했다. 아마도 메모리 폭발을 일으킨 이전 버전에 버그가있을 수 있습니다. 다음에 Pandas에서 큰 DataFrame을 읽을 때 다시 시도해 보겠습니다. (저는 이러한 작업을 위해 현재 Blaze를 주로 사용하고 있습니다)

6

아래는 내 작업 흐름입니다.

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)

데이터베이스에 모든 데이터를 저장 한 후 데이터베이스에서 필요한 데이터를 쿼리 할 수 ​​있습니다.


3

거대한 csv 파일을로드하려면 dask가 좋은 옵션 일 수 있습니다. 그것은 pandas api를 모방하므로 pandas와 매우 비슷하게 느껴집니다.

github의 dask에 링크


고마워, 내가 이것을 게시 한 이후로 나는 dask와 쪽모이 세공 형식을 사용하고 있습니다.
— Zelazny7

1

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.