类似于pandas GroupBy to List post,我们正在尝试在dask
中运行此过程。
我们当前的解决方案实现了dataframe.apply function。由于这是我们流程中的瓶颈-还有其他选择吗?
贝娄是使用dask.datasets.timeseries
数据的示例代码。
import dask
import dask.dataframe as dd
import pandas as pd
def set_list_att2(x: dd.Series):
return list(set([item for item in x.values]))
df = dask.datasets.timeseries()
df_gb = df.groupby(df.name)
gp_col = ['x','y' ,'id']
list_ser_gb = [df_gb[att_col_gr].apply(set_list_att2,
meta=pd.Series(dtype='object', name=f'{att_col_gr}_att'))
for att_col_gr in gp_col]
df_edge_att = df_gb.size().to_frame(name="Weight")
for ser in list_ser_gb:
df_edge_att = df_edge_att.join(ser.compute().to_frame(), how='left')
df_edge_att.head()
注意
df_edge_att = df_edge_att.join(ser.compute().to_frame(), how='left')
我们另外添加了compute
,否则示例代码在最终数据帧中仅返回了1行。
答案 0 :(得分:0)
我进行了一些测试,并且肯定尝试使用dd.Aggregation
而不是apply
。看到以下结果:
%%timeit
df = dask.datasets.timeseries()
df_gb = df.groupby(df.name)
gp_col = ['x','y' ,'id']
list_ser_gb = [df_gb[att_col_gr].apply(set_list_att2,
meta=pd.Series(dtype='object', name=f'{att_col_gr}_att'))
for att_col_gr in gp_col]
df_edge_att = df_gb.size().to_frame(name="Weight")
for ser in list_ser_gb:
df_edge_att = df_edge_att.join(ser.to_frame(), how='left')
df_edge_att.head()
结果是:
每个循环5分钟44s±11.2 s(平均±标准偏差,共运行7次,每个循环1次)
但是与dd.Aggregation
一起运行有很大的改进:
%%timeit
df = dask.datasets.timeseries()
custom_agg = dd.Aggregation(
'custom_agg',
lambda s: s.apply(set),
lambda s: s.apply(lambda chunks: list(set(itertools.chain.from_iterable(chunks)))),
)
df_gb = df.groupby(df.name)
gp_col = ['x','y' ,'id']
list_ser_gb = [df_gb[att_col_gr].agg(custom_agg) for att_col_gr in gp_col]
df_edge_att = df_gb.size().to_frame(name="Weight")
for ser in list_ser_gb:
df_edge_att = df_edge_att.join(ser.to_frame(), how='left')
df_edge_att.head()
结果是:
每个循环2分钟±1.13 s(平均±标准偏差,共运行7次,每个循环1次)