パンダの大規模で永続的なDataFrame


91

私は、長年のSASユーザーとしてpythonとpandasへの切り替えを検討しています。

しかし、今日いくつかのテストを実行しているときpandas.read_csv()、128mbのcsvファイルを書き込もうとすると、Pythonがメモリ不足になって驚いた。約200,000行と200列の大部分が数値データでした。

SASを使用すると、csvファイルをSASデータセットにインポートでき、ハードドライブと同じ大きさになります。

に類似したものはありpandasますか?

私は定期的に大きなファイルを扱っており、分散コンピューティングネットワークにアクセスできません。


私はパンダに慣れていませんが、ファイルを反復処理することをお勧めします。 pandas.pydata.org/pandas-docs/stable/...
monkut

回答:


79

原則としてメモリ不足になることはないはずですが、現在read_csv、いくつかの複雑なPython内部問題によって引き起こされる大きなファイルでメモリの問題があります(これはあいまいですが、長い間知られていました:http : //github.com/pydata / pandas / issues / 407)。

現時点では完璧な解決策はありません(ここでは退屈な解決策です:ファイルを行ごとに事前に割り当てられたNumPy配列またはメモリマップファイルに転記できます- np.mmap)が、私が作業することになる近い将来に。別の解決策は、ファイルを小さい部分で読み取り(を使用iterator=True, chunksize=1000)、連結してからにすることpd.concatです。問題は、テキストファイル全体を1つの大きな丸呑みでメモリにプルするときに発生します。


1
ファイルを読み取って、それらすべてを1つのDataFrameに連結できるとします。DataFrameはメモリに常駐する必要がありますか?SASでは、ハードドライブの容量さえあれば、どのようなサイズのデータ​​セットでも操作できます。DataFramesと同じですか?RAMによって制約されており、ハードドライブの容量ではないという印象を受けます。noobの質問でごめんね。助けてくれてありがとう。私はあなたの本を楽しんでいます。
Zelazny7

3
右、あなたはRAMによって制約されています。SASは確かに、「コア外」のビッグデータ処理をはるかにサポートしています。
ウェスマッキーニー2012

5
@WesMcKinneyこれらの回避策は、0.10に着陸した新しいcsvローダーのため、もう必要ありません。
ガブリエルグラント

79

ウェスはもちろん正しい!もう少し完全なサンプルコードを提供するために、ただ準備をしています。私は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)か?
アンディヘイデン

@smciは、x4(550 Mb)またはx8(1.1Gb)を繰り返した同じデータでこれをすばやく試しました。興味深いことに、[x for x in tp]の有無にかかわらず、x4は問題なく通過し、x8はMemoryErrorでクラッシュしました。
fickludd 2013年

3
使用中に次のエラーが表示されます:AssertionError: first argument must be a list-like of pandas objects, you passed an object of type "TextFileReader"。ここで何が起こっているのでしょうか?
クマール王子2014

3
このバグは0.14(近日リリース)、github.com / pydata / pandas / pull / 6941で修正される予定です。0.14.0未満の回避策は次のとおりですpd.concat(list(tp), ignore_index=True)
ジェフ

1
値が文字列またはカテゴリの場合-エラーが発生します:カテゴリ連結の互換性のないカテゴリ
As3adTintin

41

これは古いスレッドですが、回避策の解決策をここにダンプしたいと思います。私は最初にchunksizeパラメーターを試しました(たとえ10000のような非常に小さな値でも)。メモリサイズにまだ技術的な問題がありました(私のCSVは〜7.5 Gbでした)。

現在、私は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()    

4
チャンクされた読み取り機能の現実的な使用例を見るのに非常に便利です。ありがとう。
Alex Kestner 2015年

5
ほんの少しの注釈ですが、この古いトピックpandas.read_csvに対して、単純にiterator=Trueandを指定した場合、(少なくとも現在使用しているバージョンでは)イテレータを直接返しますchunksize=chunksize。したがって、毎回再インスタンス化するのではなくforpd.read_csv呼び出しに対してループを実行するだけです。ただし、これによって発生するのは呼び出しのオーバーヘッドのみであり、大きな影響はない可能性があります。
ジョエル

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が良いオプションかもしれません。パンダAPIを模倣しているため、パンダに非常によく似ています。

githubのdaskへのリンク


ありがとう、これを投稿して以来、daskと寄木細工のフォーマットを使用してきました。
Zelazny7 2017年

1

pandas dfではなくPytableを使用できます。大きなデータセット用に設計されており、ファイル形式はhdf5です。したがって、処理時間は比較的高速です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.