web-dev-qa-db-ja.com

python)で大きなデータファイルをストリーミングして操作する方法

カテゴリ間で合計してサイズを縮小したい比較的大きな(1 GB)テキストファイルがあります。

_Geography AgeGroup Gender Race Count
County1   1        M      1    12
County1   2        M      1    3
County1   2        M      2    0
_

に:

_Geography Count
County1   15
County2   23
_

ファイル全体がメモリに収まる場合、これは簡単なことですが、pandas.read_csv()を使用するとMemoryErrorが得られます。だから私は他の方法を検討してきました、そして多くのオプションがあるようです-HDF5? itertoolsを使用する(複雑に思えます-ジェネレーター?)または、標準のファイルメソッドを使用して最初の地域(70行)を読み取り、カウント列を合計し、別の70行にロードする前に書き出します。

誰かがこれを行うための最良の方法について何か提案がありますか?私は特に、データをストリーミングするというアイデアが好きです。特に、これが役立つ他の多くの場所を考えることができるからです。私はこの方法、または同様に可能な限り最も基本的な機能を使用する方法に最も興味があります。

編集:この小さなケースでは、地理的なカウントの合計のみが必要です。ただし、チャンクを読み込んで、任意の関数を指定し(たとえば、2つの列を合計するか、地理的に1列の最大値を取得する)、関数を適用して、新しいチャンクを読み込む前に出力を書き込むことができれば理想的です。 。

8
HFBrowning

dask.dataframe 、構文的にはpandasに似ていますが、コア外の操作を実行するため、メモリは問題になりません。

import dask.dataframe as dd

df = dd.read_csv('my_file.csv')
df = df.groupby('Geography')['Count'].sum().to_frame()
df.to_csv('my_output.csv')

または、pandasが要件である場合は、@ chrisaycockで説明されているように、チャンク読み取りを使用できます。 chunksizeパラメーターを試してみることをお勧めします。

# Operate on chunks.
data = []
for chunk in pd.read_csv('my_file.csv', chunksize=10**5):
    chunk = chunk.groupby('Geography', as_index=False)['Count'].sum()
    data.append(chunk)

# Combine the chunked data.
df = pd.concat(data, ignore_index=True)
df = df.groupby('Geography')['Count'].sum().to_frame()
df.to_csv('my_output.csv')
12
root

私は@rootのソリューションが好きですが、メモリ使用量をさらに最適化するつもりです-集約されたDFのみをメモリに保持し、本当に必要な列のみを読み取る:

cols = ['Geography','Count']
df = pd.DataFrame()

chunksize = 2   # adjust it! for example --> 10**5
for chunk in (pd.read_csv(filename,
                          usecols=cols,
                          chunksize=chunksize)
             ):
    # merge previously aggregated DF with a new portion of data and aggregate it again
    df = (pd.concat([df,
                     chunk.groupby('Geography')['Count'].sum().to_frame()])
            .groupby(level=0)['Count']
            .sum()
            .to_frame()
         )

df.reset_index().to_csv('c:/temp/result.csv', index=False)

テストデータ:

Geography,AgeGroup,Gender,Race,Count
County1,1,M,1,12
County2,2,M,1,3
County3,2,M,2,0
County1,1,M,1,12
County2,2,M,1,33
County3,2,M,2,11
County1,1,M,1,12
County2,2,M,1,111
County3,2,M,2,1111
County5,1,M,1,12
County6,2,M,1,33
County7,2,M,2,11
County5,1,M,1,12
County8,2,M,1,111
County9,2,M,2,1111

output.csv:

Geography,Count
County1,36
County2,147
County3,1122
County5,24
County6,33
County7,11
County8,111
County9,1111

このアプローチを使用するPSは、巨大なファイルを処理できます。

データを並べ替える必要がない限り、チャンキングアプローチを使用したPPSは機能するはずです。この場合、最初にデータを並べ替えるためにawksortなどの従来のUNIXツールを使用します。

また、CSVファイルの代わりにPyTables(HDF5ストレージ)を使用することをお勧めします。これは非常に高速で、条件付きでデータを読み取ることができるため(whereパラメーターを使用)、非常に便利で、多くのリソースを節約できます。通常 はるかに高速 CSVと比較して。

4
MaxU