web-dev-qa-db-ja.com

大きなcsvをhdf5に変換する

合計84GBの1億行のCSVファイル(実際には多くの個別のCSVファイル)があります。単一のフロートデータセットを持つHDF5ファイルに変換する必要があります。私はh5pyを問題なくテストに使用しましたが、今ではメモリが不足しないと最終的なデータセットを実行できません。

データセット全体をメモリに保存せずにHDF5に書き込むにはどうすればよいですか?ここでは実際のコードを期待しています。これは非常にシンプルなはずだからです。

pytablesを調べただけですが、配列クラス(HDF5データセットに対応)を繰り返し書き込むことができるようには見えません。同様に、pandasにはread_csvおよびto_hdfメソッドのio_tools、ただし、一度にデータセット全体をロードすることはできないため、機能しません。おそらく、pytablesまたはpandasの他のツールを使用して、問題を正しく解決するのを手伝うことができます。

25
jmilloy

append=Trueの呼び出しでto_hdfを使用

import numpy as np
import pandas as pd

filename = '/tmp/test.h5'

df = pd.DataFrame(np.arange(10).reshape((5,2)), columns=['A', 'B'])
print(df)
#    A  B
# 0  0  1
# 1  2  3
# 2  4  5
# 3  6  7
# 4  8  9

# Save to HDF5
df.to_hdf(filename, 'data', mode='w', format='table')
del df    # allow df to be garbage collected

# Append more data
df2 = pd.DataFrame(np.arange(10).reshape((5,2))*10, columns=['A', 'B'])
df2.to_hdf(filename, 'data', append=True)

print(pd.read_hdf(filename, 'data'))

利回り

    A   B
0   0   1
1   2   3
2   4   5
3   6   7
4   8   9
0   0  10
1  20  30
2  40  50
3  60  70
4  80  90

テーブルを追加可能にするには、format='table'への最初の呼び出しでdf.to_hdfを使用する必要があることに注意してください。それ以外の場合、形式はデフォルトで'fixed'になり、読み取りと書き込みは高速になりますが、追加できないテーブルが作成されます。

したがって、各CSVを一度に1つずつ処理し、append=Trueを使用してhdf5ファイルを作成できます。次に、DataFrameを上書きするか、del dfを使用して、古いDataFrameのガベージコレクションを許可します。


または、df.to_hdfを呼び出す代わりに、 HDFStoreに追加

import numpy as np
import pandas as pd

filename = '/tmp/test.h5'
store = pd.HDFStore(filename)

for i in range(2):
    df = pd.DataFrame(np.arange(10).reshape((5,2)) * 10**i, columns=['A', 'B'])
    store.append('data', df)

store.close()

store = pd.HDFStore(filename)
data = store['data']
print(data)
store.close()

利回り

    A   B
0   0   1
1   2   3
2   4   5
3   6   7
4   8   9
0   0  10
1  20  30
2  40  50
3  60  70
4  80  90
33
unutbu

これはPyTablesで可能になるはずです。ただし、 EArray クラスを使用する必要があります。

例として、以下は、.npyファイルとして保存されたチャンク化されたトレーニングデータを単一の.h5ファイルにインポートするために記述したスクリプトです。

import numpy
import tables
import os

training_data = tables.open_file('nn_training.h5', mode='w')
a = tables.Float64Atom()
bl_filter = tables.Filters(5, 'blosc')   # fast compressor at a moderate setting

training_input =  training_data.create_earray(training_data.root, 'X', a,
                                             (0, 1323), 'Training Input',
                                             bl_filter, 4000000)
training_output = training_data.create_earray(training_data.root, 'Y', a,
                                             (0, 27), 'Training Output',
                                             bl_filter, 4000000)

for filename in os.listdir('input'):
    print "loading {}...".format(filename)
    a = numpy.load(os.path.join('input', filename))
    print "writing to h5"
    training_input.append(a)

for filename in os.listdir('output'):
    print "loading {}...".format(filename)
    training_output.append(numpy.load(os.path.join('output', filename)))

詳細な手順についてはドキュメントをご覧ください。ただし、非常に簡単に、create_earray関数は1)データルートまたは親ノードを取ります。 2)配列名。 3)データ型アトム; 4)展開するディメンションに0を持つ図形。 5)詳細な記述子; 6)a 圧縮フィルター ; 7)拡張可能ディメンションに沿った予想行数。最初の2つだけが必要ですが、おそらく実際には7つすべてを使用します。この関数は、他のいくつかのオプションの引数も受け入れます。再度、詳細についてはドキュメントを参照してください。

配列が作成されたら、そのappendメソッドを期待どおりに使用できます。

6
senderle