我有一个与此类似的巨大的Dask数据框
|Ind| C1 | C2 |....| Cn |
|-----------------------|
| 1 |val1| AE |....|time|
|-----------------------|
| 2 |val2| FB |....|time|
|-----------------------|
|...|....| .. |....| ...|
|-----------------------|
|n-1|valx| ZK |....|time|
| n |valn| QK |....|time|
我想根据C2列的唯一值对其重新分区,然后将函数映射到每个分区。
首先,我将C2设置为索引:
df = dd.readcsv(...)
df = df.set_index(df.C2)
现在,我想对新索引的数据帧重新分区,然后将函数映射到每个分区。我当前的方法如下:
unique_c2 = df.index.unique().compute()
df = df.repartition(division=list(unique_c2))
# list(unique_c2) looks like this: ['AE', 'FB', ..., 'ZK', 'QK']
df.map_partitions(lambda x: my_func(x), meta=df)
我想要的分区应如下所示:
|Ind | C1 | C2 |....| Cn |
|------------------------|
| AE |val1| AE |....|time|
|------------------------|
| AE |val2| AE |....|time|
|------------------------|
|....|....| .. |....| ...|
|------------------------|
| AE |valn| AE |....|time|
...
|Ind | C1 | C2 |....| Cn |
|------------------------|
| ZK |val1| ZK |....|time|
|------------------------|
| ZK |val2| ZK |....|time|
|------------------------|
|....|....| .. |....| ...|
|------------------------|
| ZK |valn| ZK |....|time|
|Ind | C1 | C2 |....| Cn |
|------------------------|
| QK |val1| QK |....|time|
|------------------------|
| QK |val2| QK |....|time|
|------------------------|
|....|....| .. |....| ...|
|------------------------|
| QK |valn| QK |....|time|
但是重新分区函数“合并”了我的最后两个索引,所以我的最后一个分区看起来像这样:
|Ind | C1 | C2 |....| Cn |
|------------------------|
| ZK |val1| ZK |....|time|
|------------------------|
| ZK |val2| ZK |....|time|
|------------------------|
|....|....| .. |....| ...|
|------------------------|
| QK |valn| QK |....|time|
|------------------------|
|....|....| .. |....| ...|
|------------------------|
| QK |valn| QK |....|time|
为什么会发生这种情况,或者您对我的问题有更好的解决方案?我知道有一个dask.groupby(...).apply(...)
。但是我的映射函数有副作用,并且apply(...)
总是按设计对每个dask分区执行两次。
答案 0 :(得分:2)
由于分区的设计方式,分区的数量始终为(分区的数量+ 1)。来自docs:
分区包括每个分区索引的最小值, 最后一个分区的索引的最大值。
由于设置了divisions=list(unique_c2)
,因此与唯一的c2值的划分数目相同,因此要进行划分。因此,分区数将比您想要的少一分。
您可以通过将代码更改为以下内容来解决此问题:
unique_c2_list = list(df.index.unique().compute()) df = df.repartition(divisions=sorted(unique_c2_list + [unique_c2_list[-1]]))
这会将最后一个唯一的c2值添加到除法列表的末尾。对于最后的划分,c2的最小值和最大值将相同,因此这将产生所需数量的分区,并防止最后两个分区合并。