Dask分组操作中保留Pandas元组列表格式的方法求助
如何在Dask groupby.apply中保留元组列表格式?
将Pandas DataFrame转换为Dask DataFrame后,执行groupby并应用函数时,原数据中的元组列表会被转为列表列表,导致数据格式变化。以下是可复现的示例:
import pandas as pd import dask.dataframe as dd abc = [[("a", 1), ("b", 2)], [("a", 1), ("b", 2)], [("a", 1), ("b", 2)], [("a", 1), ("b", 2)]] mnp = [1, 1, 2, 3] pdf1 = pd.DataFrame() pdf1["a"] = abc pdf1["b"] = mnp ddf = dd.from_pandas(pdf1, npartitions=2) def apply_fun(grouped_df): print(grouped_df) return grouped_df # Pandas版本执行 pdf1.groupby(["b"]).apply(apply_fun) # Dask版本执行 ddf.groupby(["b"]).apply(apply_fun, meta=pd.Series([], dtype=str)).compute()
Pandas版本输出:
a b 0 [(a, 1), (b, 2)] 1 1 [(a, 1), (b, 2)] 1 a b 2 [(a, 1), (b, 2)] 2 a b 3 [(a, 1), (b, 2)] 3
Dask版本输出:
a b 0 [[a, 1], [b, 2]] 1 1 [[a, 1], [b, 2]] 1 a b 2 [[a, 1], [b, 2]] 2 a b 3 [[a, 1], [b, 2]] 3
解决方法
1. 在apply函数中手动转换回元组列表
Dask在数据分区序列化/反序列化过程中会将元组转为列表,可在自定义的apply函数里将列内的元素重新转回元组:
def apply_fun(grouped_df): # 把列表列表转回元组列表 grouped_df['a'] = grouped_df['a'].apply(lambda lst: [tuple(item) for item in lst]) print(grouped_df) return grouped_df # 执行时确保meta匹配原DataFrame结构 ddf.groupby(["b"]).apply(apply_fun, meta=pdf1).compute()
2. 正确设置meta参数
原代码中meta=pd.Series([], dtype=str)不符合DataFrame的结构,指定与原Pandas DataFrame一致的元数据,帮助Dask正确识别数据类型:
# 使用原DataFrame的dtypes作为meta ddf.groupby(["b"]).apply(apply_fun, meta=pdf1.dtypes).compute() # 或者手动指定meta结构 meta = pd.DataFrame({ 'a': object, # 元组列表属于object类型 'b': int }) ddf.groupby(["b"]).apply(apply_fun, meta=meta).compute()
3. 提前对列进行类型声明(可选)
在创建Dask DataFrame前,可先对Pandas列进行更明确的类型标记,减少序列化时的类型转换:
# 确保列a的每个元素都是元组列表 pdf1['a'] = pdf1['a'].astype('object') ddf = dd.from_pandas(pdf1, npartitions=2) ddf.groupby(["b"]).apply(apply_fun, meta=pdf1).compute()
内容的提问来源于stack exchange,提问作者jsanjayce
相关产品推荐
相关产品推荐

