基于列或函数的Dask数据框拆分分区

Rog*_*mas 5 python dataframe pandas dask dask-distributed

我最近开始在Dask寻找大数据。我对有效并行应用操作有疑问。

说我有一些这样的销售数据:

customerKey产品Key交易Key总销售净销售额单位销售量交易日期
----------- -------------- ---------------- --------- --------- ---------- ------ --------------------
    20353 189 219548 0.921058 0.921058 1 1 2017-02-01 00:00:00
  2596618 189 215015 0.709997 0.709997 1 1 2017-02-01 00:00:00
 30339435 189 215184 0.918068 0.918068 1 1 2017-02-01 00:00:00
 32714675 189 216656 0.751007 0.751007 1 1 2017-02-01 00:00:00
 39232537 189 218180 0.752392 0.752392 1 1 2017-02-01 00:00:00
 41722826 189 216806 0.0160143 0.0160143 1 1 2017-02-01 00:00:00
 46525123 189 219875 0.469437 0.469437 1 1 2017-02-01 00:00:00
 51024667 189 215457 0.244886 0.244886 1 1 2017-02-01 00:00:00
 52949803 189 215413 0.837739 0.837739 1 1 2017-02-01 00:00:00
 56526281 189 220261 0.464716 0.464716 1 1 2017-02-01 00:00:00
 56776211 189 220017 0.272027 0.272027 1 1 2017-02-01 00:00:00
 58198475 189 215058 0.805758 0.805758 1 1 2017-02-01 00:00:00
 63523098 189 214821 0.479798 0.479798 1 1 2017-02-01 00:00:00
 65987889 189 217484 0.122769 0.122769 1 1 2017-02-01 00:00:00
 74607556 189 220286 0.564133 0.564133 1 1 2017-02-01 00:00:00
 75533379 189 217880 0.164387 0.164387 1 1 2017-02-01 00:00:00
 85676779 189 215150 0.0180961 0.0180961 1 1 2017-02-01 00:00:00
 88072944 189 219071 0.492753 0.492753 1 1 2017-02-01 00:00:00
 90233554 189 216118 0.439582 0.439582 1 1 2017-02-01 00:00:00
 91949008 189 220178 0.1893 0.1893 1 1 2017-02-01 00:00:00
 91995925 189 215159 0.566552 0.566552 1 1 2017-02-01 00:00:00

我想做几个不同的groupby,首先在customerKey上应用groupby。然后应用customerKey上的另一个groupby-sum和一个将作为previos groupby结果的列。

我能想到的最有效的方法是将数据帧拆分为客户密钥块的分区。因此,例如,我可以使用分区方案将数据帧分为4个块,例如(pseudocode)

按customerKey%4划分

然后,我可以使用map_partitions对每个分区进行分组,然后最后返回结果。但是,似乎模糊迫使我对我想做的每个分组进行洗牌。

有没有办法根据列的值重新分区?

目前,在只有约80,000行的数据帧上,有4个工作人员需要大约45s。我正计划将其扩展到数以万亿计的行的数据帧,而且似乎已经开始可怕地扩展了。

我是否错过了Dask的基础知识?

MRo*_*lin 6

您可以将列设置为索引

df = df.set_index('customerKey')
Run Code Online (Sandbox Code Playgroud)

这将按该列对数据进行排序,并跟踪哪个分区中的值范围。如您所知,这可能是一项昂贵的操作,您可能需要将其保存在某个位置

在内存中

df = df.persist()
Run Code Online (Sandbox Code Playgroud)

或在磁盘上

df.to_parquet('...')
df = df.read_parquet('...')
Run Code Online (Sandbox Code Playgroud)

  • 呵呵,因此,如果将索引设置为customerKey,则可以确保每个分区中都有孤立的customerKeys块。太酷了,谢谢。将索引设置为列,然后执行df = df.map_partitions(f).compute(),其中f是相当大的功能,这是使用dask数据帧时的标准做法。对于我正在尝试执行的操作,这似乎是最有效的解决方案,但在文档中并未真正提及太多。 (4认同)
  • 这两种方法我都试过了,groupby-apply 的时间比 map_partitions 长十倍 (4认同)