在将大型Pandas数据框保存为hdf时出现OverflowError。
在将大型Pandas数据框保存为hdf时出现OverflowError。
我有一个非常大的Pandas数据框(约15GB,8300万行),我希望将其保存为一个h5(或feather)文件。其中一列包含长的ID数字字符串,应该是字符串/对象类型。但是,即使我确保pandas将所有列解析为对象类型:
df = pd.read_csv('data.csv', dtype=object)
print(df.dtypes) # 检查一下
df.to_hdf('df.h5', 'df')
> client_id object
event_id object
account_id object
session_id object
event_timestamp object
# 等等...
我得到以下错误:
File "foo.py", line 14, in
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
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
显然它仍然试图将其转换为整数,并失败了。
当运行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')
所以:
- 是否任何看起来像数字的内容都会被强制转换为数字存储?
- NaN的存在是否会影响这里发生的情况?
- 是否有其他的存储解决方案?什么是最好的选择?
在保存大型Pandas数据框到hdf时出现了OverflowError错误。问题的原因是处理字符串类型的列。字符串列包含了数字和字符混合的字符串。Pandas可以将字符串保持为object类型,即没有声明的类型。但是,当序列化为hdf5或feather时,列的内容会被转换为一种类型(例如str或double),不能混合存在。当遇到具有足够大的混合类型的数据集时,这两个库都会失败。
将混合列强制转换为字符串使我能够保存到feather文件中,但是在HDF5中,文件会膨胀并且在磁盘空间耗尽时进程终止。
这是一个类似情况的答案,其中评论者(两年前)指出:“这个问题非常常见,但解决方案很少”。
一些背景知识:
Pandas中的字符串类型称为object,但这使得它们可以是纯字符串或混合dtype(numpy有内置的字符串类型,但Pandas从不用于文本)。因此,在这种情况下要做的第一件事是将所有字符串列强制转换为字符串类型(使用df[col].astype(str))。但即使如此,在足够大的文件中(16GB,带有长字符串),仍然会失败。为什么?
我遇到这个错误的原因是我有一些长且高熵(具有许多不同唯一值)的字符串数据。在低熵数据中,切换到categorical dtype可能是值得的。在我的情况下,我意识到我只需要这些字符串来标识行 - 因此我可以用唯一的整数替换它们!
其他解决方案:
对于文本数据,有其他推荐的解决方案,而不是使用hdf5/feather,包括:
- json
- msgpack(注意,在Pandas 0.25中,read_msgpack已被弃用)
- pickle(已知存在安全问题,所以请小心使用,但对于数据框的内部存储/传输应该是可以的)
- parquet,它是Apache Arrow生态系统的一部分。
这是dask开发人员之一Matthew Rocklin的答案,比较了msgpack和pickle。他在他的博客上写了一个更广泛的比较。
(注意,sklearn的LabelEncoder与我在代码中的功能相同)
文章标题:解决将大型Pandas数据框保存为hdf时出现的OverflowError错误
文章摘要:本文介绍了在将大型Pandas数据框保存为hdf时可能出现的OverflowError错误的原因,并提供了解决方法。文章指出,对于单个时间序列事件的数据框,推荐使用Apache Arrow项目的格式,例如feather或parquet。此外,文章还提到了数据类型的问题,feather支持更多的数据类型,而parquet则提供了更高效的压缩。
正文:
在使用Pandas将大型数据框保存为hdf时,可能会遇到OverflowError错误。这是由于hdf5并不适合这种用例。hdf5更适合用于存储多个数据框的单个结构,它在打开文件时的开销更大,但可以高效地加载每个数据框,以及轻松加载它们的片段。可以将其视为存储数据框的文件系统。
对于单个时间序列事件的数据框,推荐使用Apache Arrow项目的格式,例如feather或parquet。feather和parquet都可以被视为基于列的(压缩的)csv文件。两者之间的具体区别可以在stackoverflow上找到(链接:https://stackoverflow.com/questions/48083405#48097717)。
需要考虑的一个特定问题是数据类型。由于feather不是为了通过压缩来优化磁盘空间,因此它可以支持更多的数据类型。而parquet则致力于提供非常高效的压缩,但只能支持有限的数据类型,以便更好地处理数据压缩。
因此,为了解决将大型Pandas数据框保存为hdf时出现的OverflowError错误,可以考虑使用feather或parquet格式进行存储。如果数据框包含单个时间序列事件,推荐使用feather格式;如果需要更高效的压缩,则推荐使用parquet格式。使用feather或parquet格式存储数据框可以避免OverflowError错误,并提供更好的数据压缩和读取效率。
希望本文对解决将大型Pandas数据框保存为hdf时出现的OverflowError错误提供了有帮助的解决方法。