按行块处理 dask 数据帧

时间:2021-01-21 17:06:50

标签: python pandas dask

我有一个使用特定 blocksize 块创建的 dask 数据帧:

df = dd.read_csv(filepath, blocksize = blocksize * 1024 * 1024)

我可以像这样分块处理它:

partial_results = []
for partition in df.partitions:
    partial = trivial_func(partition[var])
    partial_results.append(partial)
result = delayed(sum)(partial_results)

(这里我尝试使用 map_partitions,但最终只使用了 for 循环)。直到这部分一切正常。

现在,我需要对相同的数据运行一个函数,但是这个函数需要一个来接收数据帧的一定数量的行(例如rows_per_chunk=60),这可以实现吗?。对于熊猫,我会这样做:

partial_results = []
for i in range(int(len_df/rows_per_chunk)): # I think ceil would be better if decimal
    arg_data = df.iloc[i*rows_per_chunk:(i+1)*rows_per_chunk]
    partial = not_so_trivial_func(arg_data)
    partial_results.append(partial)
result = sum(partial_results)

可以用 dask 做这样的事情吗?我知道由于延迟评估,无法使用 iloc,但是是否可以以不同的方式对数据帧进行分区?如果不是,那么使用 dask 实现这一目标的最有效方法是什么?数据帧有数百万行。

1 个答案:

答案 0 :(得分:1)

您可以沿着定义如何跨分区分配索引值的分区重新分区数据帧(假设索引是唯一的)。

SELECT 
DATEADD(S, t.dateCreated / 1000, CAST('1970-01-01' as datetime)), 
    t.user, t.machine   
FROM
    table t

如果索引未知,则可以创建一个新索引(假设行不需要排序)并沿着计算的除法重新分区:

import dask.dataframe as dd
import pandas as pd

df = pd.DataFrame(range(15), columns=['x'])
ddf = dd.from_pandas(df, npartitions=3)

# there will 5 rows per partition
print(ddf.map_partitions(len).compute())

# you can see that ddf is split along these index values
print(ddf.divisions)

# change the divisions to have the desired spacing
new_divisions = (0, 3, 6, 9, 12, 14)
new_ddf = ddf.repartition(divisions=new_divisions)

# now there will be 3 rows per partition
print(new_ddf.map_partitions(len).compute())