我正在使用带有dask的python 3来读取实木复合地板文件列表,进行一些处理,然后将其全部放入一个新的统一实木复合地板文件中以备后用。
该进程占用了太多内存,似乎试图将所有实木复合地板文件读入内存,然后再将其写入新的实木复合地板文件中。
我正在使用以下代码
def t(path):
import dask.dataframe as dd
ddf = dd.read_parquet(path)
ddf["file"] = path
return ddf
b = bag.from_sequence(parquet_files)
with ProgressBar():
data = b.map(lambda x: t(x)).\
map(lambda y: dd.to_parquet(y, output_parquet_file, partition_on=["file"], append=True, engine="fastparquet")).\
compute(num_workers=1)
每次使用一个工作程序时,尤其是使用更多工作程序时,内存都会爆炸。文件很大(每个文件大约1G),我试图从csv文件中读取信息并将它们分成25M块,并遇到了同样的问题。
我在这里想念什么?当似乎迭代过程是正确的选择时,为什么它尝试将所有内容加载到内存中?如何在不消耗那台机器上128G内存的情况下使用dask操作呢?
PS,我尝试使用pyarrow引擎,但问题是dask尚未实现append。
编辑:尝试过的建议解决方案: 我现在尝试此代码
import dask.dataframe as dd
with ProgressBar():
dfs = [dd.read_parquet(pfile) for pfile in parquet_files]
for i, path in enumerate(parquet_files):
dfs[i]["file"] = path
df = dd.concat(dfs)
df.to_parquet(output_parquet_file)
而且,内存爆炸(在具有200G以上内存的系统上)
答案 0 :(得分:2)
在另一个集合上的地图中使用dask集合方法很奇怪。您可以像这样使用bag.map
并直接调用fastaprquet函数,或者可能更好(取决于您需要执行的处理),使用dataframe API进行所有操作:
dfs = [dd.read_parquet(pfile, ...) for pfile in parquet_files]
df = dd.concat(dfs)
df.to_parquet(...)
请注意,尽管您尝试附加到单个文件(我认为),镶木地板格式并不能真正从中受益,您也可以让Dask为每个分区写一个文件。
答案 1 :(得分:0)
dask 支持将多个 parquet 文件作为分区读取。 直接调用就行了。
import dask.dataframe as dd
ddf = dd.read_parquet("parquets/*.parquet")
ddf = ddf.map_partitions(lambda df: df*2)
ddf.to_parquet("result.parquet")