python - 如果满足某些条件,则在组内将日期移动到上一年的同一日期

标签 python pandas dataframe

我有一个看起来像这样的 pandas 数据框

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

最佳答案

让我们在 shift() 月份系列上尝试 ffill()

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 - 如果满足某些条件,则在组内将日期移动到上一年的同一日期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62876421/

相关文章:

python - 使用函数将每个第二个单词替换为单词 'hello'

python - 属性错误: 'Series' object has no attribute 'columns' in Dask

r - 根据行名匹配两个数据框并添加 NA

python-3.x - 根据条件去除重复

python - 如何按日期时间分组的 pandas 数据框中的状态更改列进行聚合

python - 如何在pandas数据框中按特定条件进行分组

dataframe - julia 数据框更改一个单元格会更改整行

python - 在 python 的记录器中分离 stdout 和 stderr

python - 如何依赖 python/distutils 的系统命令?

python - 将整数写入文件