python - 如果满足某些条件,则在组内移动日期到上一年的同一日期
问题描述
我有一个看起来像这样的熊猫数据框
pd.DataFrame({'a':['cust1', 'cust1', 'cust1', 'cust1', 'cust1', 'cust1', 'cust1', 'cust2', 'cust2', 'cust3', 'cust3', 'cust3'],
'date':[date(2017, 6, 15), date(2017, 12, 15), date(2018, 6, 15), date(2019, 1, 20), date(2019, 6, 15), date(2020, 1, 10), date(2020, 6, 12), date(2017, 12, 15), date(2018, 12, 10), date(2017, 1, 5), date(2018, 1, 15), date(2019, 2, 20)],
'c':[5, 5, 6, 6, 7, 7, 8, 4, 8, 6, 5, 9]})
a date c
0 cust1 2017-06-15 5
1 cust1 2017-12-15 5
2 cust1 2018-06-15 6
3 cust1 2019-01-20 6
4 cust1 2019-06-15 7
5 cust1 2020-01-10 7
6 cust1 2020-06-12 8
7 cust2 2017-12-15 4
8 cust2 2018-12-10 8
9 cust3 2017-01-05 6
10 cust3 2018-01-15 5
11 cust3 2019-02-20 9
a' = 客户
'date' = 客户付款的日期
'c' = 客户支付的金额
我需要检查客户每年支付的次数是否与上一年相同,但对于历史上在 12 月支付但后来在 1 月支付的客户,我想将 1 月的日期更改为 12 月的日期。
我尝试了以下方法:
year_end_month = [1, 12]
df['date'] = pd.to_datetime(df['date'], errors='coerce')
df_2 = df.loc[df['date'].dt.month.isin(year_end_month)].copy()
df_3 = pd.concat([df, df_2]).drop_duplicates(keep=False)
s=df_2.groupby('a').date.shift().dt.month
df_2['newDate']=np.where(s.eq(12) & df_2.date.dt.month.eq(1), df_2.date-
pd.DateOffset(months=1), df_2.date)
df_4 = pd.concat([df_2, df_3])
df_4.newDate = df_4.newDate.fillna(df_4.date)
df_4.sort_values(by=['a', 'date'])
我的方法的问题在于,它在付款日期第一次从 12 月移至 1 月时有效,但在随后的几年中无效。因此,查看 cust1 第一次将付款从 12 月切换到 1 月是在 2018 年 12 月到 2019 年 1 月,我的方法捕捉到了这一点。但我的方法未能将她在 2020 年 1 月支付的 2019 年付款转移到 2019 年 12 月。知道如何解决这个问题吗?
我生成的数据框应如下所示:
a date c newDate
0 cust1 2017-06-15 5 2017-06-15
1 cust1 2017-12-15 5 2017-12-15
2 cust1 2018-06-15 6 2018-06-15
3 cust1 2019-01-20 6 **2018-12-20**
4 cust1 2019-06-15 7 2019-06-15
5 cust1 2020-01-10 7 **2019-12-10**
6 cust1 2020-06-12 8 2020-06-12
7 cust2 2017-12-15 4 2017-12-15
8 cust2 2018-12-10 8 2018-12-10
9 cust3 2017-01-05 6 2017-01-05
10 cust3 2018-01-15 5 2018-01-15
11 cust3 2019-02-20 9 2019-02-20
解决方案
让我们试试ffill()
月shift()
系列
months = df.date.dt.month
s = months.eq(12).groupby(df['a']).shift()
df['date'] = np.where(months.eq(1) & s.where(s).groupby(df['a']).ffill(),
df['date'] - pd.tseries.offsets.MonthOffset(),
df['date'])
输出:
a date c
0 cust1 2017-06-15 5
1 cust1 2017-12-15 5
2 cust1 2018-06-15 6
3 cust1 2018-12-20 6
4 cust1 2019-06-15 7
5 cust1 2019-12-10 7
6 cust1 2020-06-12 8
7 cust2 2017-12-15 4
8 cust2 2018-12-10 8
9 cust3 2017-01-05 6
10 cust3 2018-01-15 5
11 cust3 2019-02-20 9
推荐阅读
- python - XML结束标记弄乱了文件
- react-native - 反应本机堆栈导航按钮 onpress 不起作用
- wordpress - 为什么 WordPress 中的页面速度得分没有增加?
- android-studio - 在包 name.ratson.cordova.admob 中构建时出错;
- android - 将额外的 Surfaces 传递给 ProcessCameraProvider::bindToLifecycle
- flask - 使用 Flask 上传到 S3 时出现 FileNotFoundError
- vue.js - Vetur 将 .vue 文件的第一行标记为错误
- android - 通过命令行使用gradle构建android应用程序时出错
- javascript - Tiny Slider 2 两排卡片
- javascript - Angular 组件在加载子组件之前不传递数据