基于分类列对数值列分箱的性能优化求助
基于分类列对数值列分箱的性能优化求助
你遇到的问题太典型了——用df.apply(axis=1)处理百万级以上的数据集,速度慢到离谱是必然的,因为apply本质上是在逐行执行Python函数,每一行都要触发一次函数调用,10^7行的话,这个开销会被放大到无法接受的程度。
咱们换个思路,既然每个SEGMENT的分箱规则是固定的,那直接按SEGMENT分组,用**向量化的pd.cut**批量处理每个分组就行,完全避开逐行循环。
优化后的代码
先保留你原来的cuts字典不变,然后替换掉apply的部分:
cuts = { "A": {"cut":[0,20240101,20240801,20241201,20250000], "class":["out", "training", "validation", "out"]}, "B": {"cut":[0,20230701,20240701,20241201,20250000], "class":["out", "training", "validation", "out"]}, "C": {"cut":[0,20230701,20240701,20250101,20250201], "class":["out", "training", "validation", "out"]} } # 初始化CLASS列 df["CLASS"] = None # 遍历每个SEGMENT的规则,批量处理 for segment, rules in cuts.items(): # 筛选当前SEGMENT的所有行 mask = df["SEGMENT"] == segment # 对筛选出的DATE列批量分箱 df.loc[mask, "CLASS"] = pd.cut( df.loc[mask, "DATE"], bins=rules["cut"], labels=rules["class"], right=False, ordered=False )
为什么这个方法快?
- 原来的
apply是Python级别的逐行循环,每一行都要调用一次divisions函数,光是函数调用的开销就足以拖垮性能; - 优化后的代码是向量化批量处理,
pd.cut是用C语言实现的底层循环,处理每个SEGMENT的所有行时,只需要执行一次分箱逻辑,速度能提升几个数量级——10^7行的话,原来可能要几十分钟,现在估计几分钟甚至几十秒就能搞定。
额外的小建议
如果你的数据集大到pandas单进程处理都有点吃力,还可以试试用Dask做并行处理,但对于这个场景来说,上面的pandas向量化方法应该已经完全够用了,毕竟逻辑简单,也不需要额外依赖。
最后确认一下:这个代码的分箱逻辑和你原来的divisions函数完全一致,right=False参数也保留了,所以生成的CLASS列结果和原来完全相同,只是速度快了N倍。
备注:内容来源于stack exchange,提问作者Théodore Targerian
相关产品推荐
相关产品推荐

