使用Dask处理大型压缩的CSV文件

3
设置如下:我有八个大的csv文件(每个文件32GB),它们被压缩为每个8GB的Zip文件。我不能使用未压缩的数据,因为我想要节省磁盘空间,而且没有剩余32*8GB的空间。我不能用例如pandas加载一个文件,因为它无法适应内存。
我认为Dask是这项任务的合理选择,但如果您认为其他工具更适合,则可以自由建议。
是否可能通过同时读取压缩文件的多个块、处理每个块并将结果保存到磁盘来处理一个8GB的压缩文件?
第一个问题是,Dask不支持.zip此问题建议使用dask.delayed,但我也可以更改格式为.xz或其他格式。
第二个问题,可能与压缩格式的选择有关,即是否可以并行访问压缩文件的部分内容。
还是将每个未压缩的csv文件拆分成适合内存的较小部分,然后使用类似以下方式处理重新压缩的较小部分更好:
import dask.dataframe as dd

df = dd.from_csv('files_*.csv.xz', compression='xz')

目前,我更偏向于第一种解决方案,因为它看起来更简洁,但由于这个领域对我来说是新的,我可能完全错了。

谢谢你的帮助!

1个回答

0

最简单的解决方案当然是将大文件流式传输到几个压缩文件中(记得在每个文件末尾加上换行符!),然后像您建议的那样使用Dask加载这些文件。每个较小的文件将成为内存中的一个数据帧分区,因此只要文件足够小,您在处理数据时就不会耗尽内存。

这里的根本原因是,格式列表bz2、gz或zip不允许随机访问,读取数据的唯一方法是从数据的开头开始。xz是唯一允许在文件内进行块状压缩的格式,因此原则上可以进行块状加载,这与真正的随机访问不完全相同。这将实现您想要的效果。但是,这种模式实际上与具有单独文件的模式完全相同,因此不值得额外的工作来以阻塞模式(而不是默认模式)编写文件并使用函数dask.bytes.compression.get_xz_blocks、xz_decompress,这些函数目前在代码库中未被使用。


我认为.bz2文件是分块压缩的。使用https://github.com/mxmlnkn/indexed_bzip2可以在Python中实现一种形式的随机访问,尽管您必须先读取文件以获取块边界,因此仅在多次读取文件时才有用。 - user2667066
没错,目前文件系统并不支持/理解这种索引方式;即使是xz也需要进行改进。对于那些有兴趣贡献的人来说,这项工作可以在fsspec中完成。我注意到indexed_bzip2只适用于本地文件。 - mdurant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接