web-dev-qa-db-ja.com

大きな保存中のOverflowError Pandas df to hdf

大きなPandasデータフレーム(〜15GB、83m行))があり、これを_h5_(またはfeather)ファイルとして保存したい。1つの列に長い数値のID文字列。これには文字列/オブジェクトタイプが必要ですが、pandasがすべての列をobjectとして解析することを確認した場合でも、

_df = pd.read_csv('data.csv', dtype=object)
print(df.dtypes)  # sanity check
df.to_hdf('df.h5', 'df')

> client_id                object
  event_id                 object
  account_id               object
  session_id               object
  event_timestamp          object
  # etc...
_

私はこのエラーを受け取ります:

_  File "foo.py", line 14, in <module>
    df.to_hdf('df.h5', 'df')
  File "/shared_directory/projects/env/lib/python3.6/site-packages/pandas/core/generic.py", line 1996, in to_hdf
    return pytables.to_hdf(path_or_buf, key, self, **kwargs)
  File "/shared_directory/projects/env/lib/python3.6/site-packages/pandas/io/pytables.py", line 279, in to_hdf
    f(store)
  File "/shared_directory/projects/env/lib/python3.6/site-packages/pandas/io/pytables.py", line 273, in <lambda>
    f = lambda store: store.put(key, value, **kwargs)
  File "/shared_directory/projects/env/lib/python3.6/site-packages/pandas/io/pytables.py", line 890, in put
    self._write_to_group(key, value, append=append, **kwargs)
  File "/shared_directory/projects/env/lib/python3.6/site-packages/pandas/io/pytables.py", line 1367, in _write_to_group
    s.write(obj=value, append=append, complib=complib, **kwargs)
  File "/shared_directory/projects/env/lib/python3.6/site-packages/pandas/io/pytables.py", line 2963, in write
    self.write_array('block%d_values' % i, blk.values, items=blk_items)
  File "/shared_directory/projects/env/lib/python3.6/site-packages/pandas/io/pytables.py", line 2730, in write_array
    vlarr.append(value)
  File "/shared_directory/projects/env/lib/python3.6/site-packages/tables/vlarray.py", line 547, in append
    self._append(nparr, nobjects)
  File "tables/hdf5extension.pyx", line 2032, in tables.hdf5extension.VLArray._append
OverflowError: value too large to convert to int
_

どうやらこれをとにかくintに変換しようとして失敗しています。

df.to_feather()を実行すると、同様の問題が発生します。

_df.to_feather('df.feather')
  File "/shared_directory/projects/env/lib/python3.6/site-packages/pandas/core/frame.py", line 1892, in to_feather
    to_feather(self, fname)
  File "/shared_directory/projects/env/lib/python3.6/site-packages/pandas/io/feather_format.py", line 83, in to_feather
    feather.write_dataframe(df, path)
  File "/shared_directory/projects/env/lib/python3.6/site-packages/pyarrow/feather.py", line 182, in write_feather
    writer.write(df)
  File "/shared_directory/projects/env/lib/python3.6/site-packages/pyarrow/feather.py", line 93, in write
    table = Table.from_pandas(df, preserve_index=False)
  File "pyarrow/table.pxi", line 1174, in pyarrow.lib.Table.from_pandas
  File "/shared_directory/projects/env/lib/python3.6/site-packages/pyarrow/pandas_compat.py", line 501, in dataframe_to_arrays
    convert_fields))
  File "/usr/lib/python3.6/concurrent/futures/_base.py", line 586, in result_iterator
    yield fs.pop().result()
  File "/usr/lib/python3.6/concurrent/futures/_base.py", line 425, in result
    return self.__get_result()
  File "/usr/lib/python3.6/concurrent/futures/_base.py", line 384, in __get_result
    raise self._exception
  File "/usr/lib/python3.6/concurrent/futures/thread.py", line 56, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/shared_directory/projects/env/lib/python3.6/site-packages/pyarrow/pandas_compat.py", line 487, in convert_column
    raise e
  File "/shared_directory/projects/env/lib/python3.6/site-packages/pyarrow/pandas_compat.py", line 481, in convert_column
    result = pa.array(col, type=type_, from_pandas=True, safe=safe)
  File "pyarrow/array.pxi", line 191, in pyarrow.lib.array
  File "pyarrow/array.pxi", line 78, in pyarrow.lib._ndarray_to_array
  File "pyarrow/error.pxi", line 85, in pyarrow.lib.check_status
pyarrow.lib.ArrowInvalid: ('Could not convert 1542852887489 with type str: tried to convert to double', 'Conversion failed for column session_id with type object')
_

そう:

  1. ストレージ内の数値に強制的に変換された数値のように見えるものはありますか?
  2. NaNの存在は、ここで何が起こっているかに影響を与える可能性がありますか?
  3. 代替のストレージソリューションはありますか?何が一番いいですか?
10

このトピックを読んだところ、問題はstringタイプの列を処理しているようです。私のstring列には、すべて数字の文字列と文字列が混在しています。 Pandasには、宣言された型なしで文字列をobjectとして保持する柔軟なオプションがありますが、hdf5またはfeatherにシリアル化すると列は型(strまたはdoubleなど)に変換され、混合することはできません。これらのライブラリは両方とも、混合型の十分に大きなライブラリに直面すると失敗します。

混合列を文字列に強制変換すると、フェザーで保存できましたが、HDF5ではファイルが膨らみ、ディスク領域がなくなるとプロセスが終了しました。

ここ は、コメンターが(2年前に)「この問題は非常に標準的ですが、解決策は少ない」と指摘する比較可能な場合の回答です。

背景:

Pandasの文字列型はobjectと呼ばれますが、これはそれらが純粋な文字列または混合dtypes(numpy has組み込みの文字列型ですが、Pandasはテキストにそれらを使用しません。)したがって、このような場合に最初に行うことは、すべての文字列の列を文字列型として強制することです(df[col].astype(str) )しかし、それでも、十分に大きいファイル(16 GB、長い文字列)では、これはまだ失敗します。

このエラーが発生した理由は、longおよびhigh-entropy(多くの異なる一意の値)文字列のデータがあったためです。 (低エントロピーデータの場合、categorical dtypeに切り替える価値があったかもしれません。)私の場合、行を識別するためにこれらの文字列だけが必要であることに気付きました-それで、それらを一意の整数に置き換えることができました!

df[col] = df[col].map(dict(Zip(df[col].unique(), range(df[col].nunique()))))

その他のソリューション:

テキストデータの場合、hdf5/feather以外の推奨される解決策があります。

  • json
  • msgpack(Pandas 0.25 read_msgpackは廃止予定であることに注意してください)
  • pickle(既知の セキュリティの問題 があるため、注意してください。ただし、データフレームの内部ストレージ/転送には問題ありません)
  • parquet、Apache Arrowエコシステムの一部。

ここ は、daskmsgpackを比較するMatthew Rocklin(pickle開発者の1人)からの回答です。彼は blog について幅広い比較を書きました。

5

HDF5は、この使用例に適したソリューションではありません。 hdf5は、単一の構造に格納したい多くのデータフレームがある場合に優れたソリューションです。ファイルを開くときのオーバーヘッドが大きくなり、各データフレームを効率的にロードし、それらのスライスを簡単にロードすることもできます。データフレームを保存するファイルシステムと考える必要があります。

時系列イベントの単一のデータフレームの場合、推奨される形式は、Apache Arrowプロジェクト形式の1つ、つまりfeatherまたはparquetです。これらは列ベースの(圧縮された)csvファイルと考える必要があります。これらの2つの間の特定のトレードオフは 羽と寄木細工の違いは何ですか? の下にうまくレイアウトされています。

考慮すべき1つの特定の問題は、データ型です。 featherは圧縮によってディスク領域を最適化するように設計されていないため、 より多様なデータ型 をサポートできます。 parquetは非常に効率的な圧縮を提供しようとしますが、データ圧縮をより適切に処理できる 限られたサブセット のみをサポートできます。

3
Alex Fish