如何在Pandas中实现类似SQL带分组滞后参数的计算?
Pandas 实现SQL分区Lag函数的简洁写法
原SQL实现逻辑
在SQL中,我们可以通过窗口函数快速实现带分区的滞后指标计算,示例如下:
CASE WHEN dt_rep.fcr = 0::numeric THEN 0::numeric ELSE (dt_rep.fcr - lag(dt_rep.fcr) OVER (PARTITION BY dt_rep.place_id ORDER BY dt_rep.bucket)) / dt_rep.fcr END AS cr
这段代码按place_id分区、bucket排序,用lag函数计算cr,最后过滤cr为null的行得到结果。
Pandas常规实现(需临时列)
在Pandas中常规做法是先生成分组移位的临时列,再计算目标列:
data_fin['fcr_b'] = data_fin.groupby(['place_id'])['fcr'].shift(1) # 后续计算cr:(data_fin['fcr'] - data_fin['fcr_b']) / data_fin['fcr'],再处理fcr=0的情况,最后过滤NaN
更简洁的直接实现方法
可以跳过临时列,直接在分组操作中完成cr列的计算,以下是两种简洁写法:
写法1:分组apply链式处理
# 直接计算cr,同时处理fcr=0的情况 data_fin['cr'] = data_fin.groupby('place_id')['fcr'].apply( lambda x: (x - x.shift(1)) / x ).where(data_fin['fcr'] != 0, 0) # 过滤掉每组第一行(移位后为NaN的行) data_fin = data_fin.dropna(subset=['cr'])
写法2:用assign链式调用,全程无临时变量
data_fin = ( data_fin .assign( cr=lambda df: df.groupby('place_id')['fcr'] .apply(lambda x: (x - x.shift(1)) / x) .where(df['fcr'] != 0, 0) ) .dropna(subset=['cr']) )
核心说明
x.shift(1)等价于SQL中的lag(dt_rep.fcr),默认滞后1行where方法对应SQL的CASE WHEN逻辑,当fcr=0时返回0,否则执行计算dropna(subset=['cr'])对应SQL中过滤cr为null的操作,移除每组的第一行(无滞后值的行)
内容的提问来源于stack exchange,提问作者OcMaRUS
相关产品推荐
相关产品推荐

