Python如何标记时间序列DataFrame近n个月列值增减
Python实现时间序列DataFrame近n个月数值变动标记
前置要求
你的客户数据集需要包含三类核心字段,提前做好基础清洗:
- 客户唯一标识字段(比如
customer_id) - 月度统计时间字段(必须为datetime类型,比如
stat_month,粒度到月即可) - 需要对比的数值字段(比如
salary即薪资) - 提前保证每个客户单月仅存在一条有效记录,避免重复数据导致计算错误
核心实现逻辑
不用写低效的逐行遍历循环,直接用pandas的分组移位功能,把当前行的薪资值和n个月前的薪资值对齐做差,根据差值正负打变动标签即可,百万级数据量也能快速跑完。
可直接复用的代码
import pandas as pd import numpy as np # -------------------------- # 第一步:基础格式处理 # -------------------------- # 替换成你自己的DataFrame变量名、实际列名 df['stat_month'] = pd.to_datetime(df['stat_month']) # 时间列转标准datetime格式 # 按客户ID、统计时间升序排序,保证每个客户的记录从早到晚排列 df = df.sort_values(by=['customer_id', 'stat_month']).reset_index(drop=True) # -------------------------- # 第二步:定义通用打标函数 # -------------------------- def mark_nmonth_change(group, col, n): """ 对单个客户的时间序列分组,标记指定列近n个月的变动情况 :param group: 单个客户的分组DataFrame :param col: 需要对比的数值列名,这里传薪资列即可 :param n: 对比的月数,比如6、12 """ # 移位获取n个月前的数值 val_n_before = group[col].shift(n) val_diff = group[col] - val_n_before # 根据差值匹配标签 res_tag = np.select( condlist=[val_n_before.isna(), val_diff > 0, val_diff < 0], choicelist=[ "无有效对比数据", f"近{n}个月上涨", f"近{n}个月下降" ], default=f"近{n}个月持平" ) return pd.Series(res_tag, index=group.index) # -------------------------- # 第三步:批量分组打标 # -------------------------- # 标记近6个月薪资变动 df['tag_6m'] = df.groupby('customer_id', group_keys=False).apply( lambda x: mark_nmonth_change(x, col='salary', n=6) ) # 标记近12个月薪资变动 df['tag_12m'] = df.groupby('customer_id', group_keys=False).apply( lambda x: mark_nmonth_change(x, col='salary', n=12) )
特殊场景处理
- 如果你的数据存在缺月(不是每个客户每个月都有记录),不要直接用shift移位:先把时间列设为索引,按客户分组后用
resample('M')重采样为连续月度序列,缺月的薪资值按业务规则用前值填充/标记为空,再执行上面的打标逻辑,避免把间隔多月的记录错当成n个月的对比对象 - 如果只需要提取最新统计周期有薪资变动的客户,先按客户分组取
stat_month最大的最新一条记录,再筛选标签为上涨/下降的行即可 - 打标前建议先过滤薪资为0、空值、异常极值的记录,避免出现误判
内容的提问来源于stack exchange,提问作者Katarina123
相关产品推荐
相关产品推荐

