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=Truechunksize내가 정확히 기억한다면 매개 변수는 이미 다시 존재했다. 아마도 메모리 폭발을 일으킨 이전 버전에 버그가있을 수 있습니다. 다음에 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.