【问题标题】:dask DataFrame.assign blows up dask graphdask DataFrame.assign 炸毁了 dask 图
【发布时间】:2017-06-18 20:39:45
【问题描述】:

所以我对 dask DataFrame.append 有疑问。我从主数据中生成了很多衍生特征,并将它们附加到主数据框中。之后,任何一组列的 dask 图都被炸毁了。这是一个小例子:

%pylab inline
import numpy as np
import pandas as pd
import dask.dataframe as dd
from dask.dot import dot_graph

df=pd.DataFrame({'x%s'%i:np.random.rand(20) for i in range(5)})
ddf = dd.from_pandas(df, npartitions=2)

dot_graph(ddf['x0'].dask)

here is the dask graph as expected

g=ddf.assign(y=ddf['x0']+ddf['x1'])
dot_graph(g['x0'].dask)

here the graph for same column is exploded with irrelevant computation

想象一下,我有很多生成的列。因此,任何特定列的计算图都包括所有其他列的不相关计算。 IE。就我而言,我有 len(ddf['someColumn'].dask)>100000。所以很快就会变得无法使用。

所以我的问题是这个问题可以解决吗?有没有现有的方法可以做到这一点?如果不是 - 我应该寻找什么方向来实现这一点?

谢谢!

【问题讨论】:

    标签: python optimization dataframe assign dask


    【解决方案1】:

    与其不断为 dask 数据框分配新列,不如构建几个 dask 系列,然后在最后将它们全部连接在一起

    所以不要这样做:

    df['x'] = df.w + 1
    df['y'] = df.x * 10
    df['z'] = df.y ** 2
    

    这样做

    x = df.w + 1
    y = x + 10
    z = y * 2
    df = df.assign(x=x, y=y, z=z)
    

    或者这个:

    dd.concat([df, x, y, z], axis=1)
    

    这可能仍会导致图表中的任务数量相同,但可能会导致内存副本减少。

    或者,如果您的所有转换都是逐行的,那么您可以构建一个 pandas 函数并将其映射到所有分区

    def f(part):
        part = part.copy()
        part['x'] = part.w + 1
        part['y'] = part.x * 10
        part['z'] = part.y ** 2
        return part
    
    df = df.map_partitions(f)
    

    此外,虽然百万节点任务图不太理想,但它也应该没问题。我已经看到较大的图表运行起来很舒服。

    【讨论】:

    • 感谢您的快速回复。我目前正在使用 df = df.assign(x=x, y=y, z=z) ,一次分配所有系列,但图中还有那些不需要这些计算的列的额外节点。有没有一种方法可以优化图形,当您获得列的子集时,它会裁剪所有其他计算?我的解决方法是计算所有内容,保存到 hdf,加载它,然后我可以按需访问某些列子集。但后来 hdf 列长度限制打击了我,我再次开始分块数据,再次选择列的子集。
    • 如果您只使用xy 而不是z,那么dask 将从计算中删除z。但是,一旦将它们全部分配到数据框中,您就会全部陷入困境。 Dask 不会像您想要的那样执行高级优化。您可以尝试坚持使用 Parquet 而不是 HDF5。读取几列也会比使用 HDF5 快得多
    • 谢谢,会试试镶木地板
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-04
    • 2018-11-25
    • 1970-01-01
    • 1970-01-01
    • 2019-04-02
    • 1970-01-01
    • 2021-12-22
    相关资源
    最近更新 更多