Pandas多操作单行代码优化及DataFrame结果匹配报错问题
问题解答
报错原因
没错,报错就是因为形状不匹配。你用groupby(['id_1','id_2'])['vio_eve'].sum()得到的是每个分组对应一个值的Series(长度2013),但原main_df有11065065行,Pandas没法把短序列的单个值自动对应到原DataFrame中该分组的所有行,自然会抛出对齐错误。
能否合并第一行逻辑到第三行?
完全可以。我们可以在一次分组聚合中同时计算vio_eve的总和、value的极差(max-min),把这些逻辑整合到一起,避免中间变量。
正确实现方式(含单行合并版本)
方式1:可读性优先(分步实现)
ml = 1000 # 一次性计算所有分组所需统计量,同时完成shift(1) group_metrics = main_df.groupby(['id_1','id_2']).agg( vio_total=('vio_eve', 'sum'), value_range=('value', lambda x: x.max() - x.min()) ).shift(1) # 将分组统计量合并回原DataFrame,确保每个分组的统计量对应到所有行 main_df = main_df.merge( group_metrics, on=['id_1', 'id_2'], how='left' ) # 计算目标列,最后清理临时列 main_df['hos_eve'] = 145 - (main_df['vio_total'] * ml) / main_df['value_range'] main_df.drop(columns=['vio_total', 'value_range'], inplace=True)
方式2:单行合并版本(满足你要的单行需求)
ml = 1000 main_df['hos_eve'] = main_df.merge(main_df.groupby(['id_1','id_2']).agg(vio_sum=('vio_eve','sum'), val_range=('value', lambda s: s.max()-s.min())).shift(1), on=['id_1','id_2'], how='left').eval('145 - (vio_sum * @ml) / val_range')
方式3:用transform直接生成对应长度结果
ml = 1000 # 先计算每个分组的hos_eve值并shift,再映射回原DataFrame group_result = main_df.groupby(['id_1','id_2']).apply( lambda g: 145 - (g['vio_eve'].sum() * ml) / (g['value'].max() - g['value'].min()) ).shift(1) main_df['hos_eve'] = main_df.set_index(['id_1','id_2']).index.map(group_result.get)
关键说明
不管哪种方式,核心都是把分组级的统计结果映射回原DataFrame的每一行,保证新列的长度和原DataFrame一致,这样就不会再报错了。
内容的提问来源于stack exchange,提问作者Sushil Kokil
相关产品推荐
相关产品推荐

