如何用Pandas计算每个用户每月的数值(如UPL)变化
问题描述
我曾查找过类似主题,但仅找到整体月度变化的实现方法。我需要按用户维度计算每月的数值变化(例如UPL),现有数据如下:
| user_id | month | UPL |
|---|---|---|
| 1 | 2022-01-01 00:00:00 | 100 |
| 1 | 2022-02-01 00:00:00 | 200 |
| 2 | 2022-01-01 00:00:00 | 100 |
| 2 | 2022-02-01 00:00:00 | 50 |
| 1 | 2022-03-01 00:00:00 | 150 |
希望新增名为“UPL_change_by_month”的列,得到如下结果:
| user_id | month | UPL | UPL_change_by_month |
|---|---|---|---|
| 1 | 2022-01-01 00:00:00 | 100 | 0 |
| 1 | 2022-02-01 00:00:00 | 200 | 100 |
| 2 | 2022-01-01 00:00:00 | 100 | 0 |
| 2 | 2022-02-01 00:00:00 | 50 | -50 |
| 1 | 2022-03-01 00:00:00 | 150 | -50 |
请问是否可以使用Pandas的aggfunc或shift函数实现该需求?
解决方案
当然可以,用Pandas的shift()函数结合分组操作就能轻松实现,不需要用到aggfunc。具体实现步骤如下:
- 先将
month列转换为日期类型,并按user_id和month排序,确保每个用户的月度数据按时间顺序排列 - 按
user_id分组后,对UPL列使用shift(1)获取每个用户上一个月的UPL值 - 用当前月份的UPL减去上月UPL得到变化值,再将每个用户的第一个月份的变化值填充为0
代码示例
import pandas as pd # 构造原始数据集 data = { 'user_id': [1, 1, 2, 2, 1], 'month': ['2022-01-01 00:00:00', '2022-02-01 00:00:00', '2022-01-01 00:00:00', '2022-02-01 00:00:00', '2022-03-01 00:00:00'], 'UPL': [100, 200, 100, 50, 150] } df = pd.DataFrame(data) # 转换日期格式并排序,保证数据时序正确 df['month'] = pd.to_datetime(df['month']) df = df.sort_values(['user_id', 'month']) # 分组计算月度UPL变化 df['UPL_change_by_month'] = df.groupby('user_id')['UPL'].transform(lambda x: x - x.shift(1)) # 填充首个月份的空值为0 df['UPL_change_by_month'] = df['UPL_change_by_month'].fillna(0).astype(int) # 输出结果 print(df)
运行结果
执行代码后将得到符合预期的输出:
| user_id | month | UPL | UPL_change_by_month |
|---|---|---|---|
| 1 | 2022-01-01 00:00:00 | 100 | 0 |
| 1 | 2022-02-01 00:00:00 | 200 | 100 |
| 1 | 2022-03-01 00:00:00 | 150 | -50 |
| 2 | 2022-01-01 00:00:00 | 100 | 0 |
| 2 | 2022-02-01 00:00:00 | 50 | -50 |
如果你的原始数据已经按user_id和month有序排列,可以跳过排序步骤,但保留排序能避免因数据混乱导致的计算错误。
内容的提问来源于stack exchange,提问作者Lukasz
相关产品推荐
相关产品推荐

