首页 > 解决方案 > 使用自定义功能将年度数据分解为月度数据

问题描述

我正在尝试按费用将年度订阅分解为每月订阅。

示例数据集-

import numpy as np
import pandas as pd

df = pd.DataFrame({
    'Customer_ID': [1, 2, 3, 4, 5],
    'Plan' : ['Yearly', 'Monthly', 'Monthly', 'Yearly', 'Yearly'],
    'Join_Date': ['1/10/2020', '1/15/2020', '2/21/2020', '2/21/2020', '3/09/2020'],
    'Fee' : [120, 12, 18, 86, 144]
})

df['Join_Date'] = pd.to_datetime(df['Join_Date'])

df

在这里,客户 1 在 2020 年 1 月至 2021 年 1 月之间的年订阅费为 120 美元。我希望我的数据框通过显示每个月将 2020 年 1 月至 2020 年 12 月之间的费用细分为 10 美元(120 美元/12 个月)年月费(10 美元)。

我尝试了一堆重采样方法,但没有奏效。一个例子——

def atom(row):
    if df.Plan=='Yearly':
        return (df.Fee/12)

df.groupby(pd.Grouper(key='Join_Date', freq='1M')).apply(atom)

第一个客户的预期输出-

在此处输入图像描述

还有其他方法吗?

标签: pythonpandaspandas-groupbyresampling

解决方案


首先将年度记录扩大np.repeat(). 然后有选择地对 执行以下操作df1["Plan"] == "Yearly"

  • 月费可以直接计算。
  • 可以使用 获取月份的增量groupby-cumcount并将其映射到pd.DateOffset(months=). 这种方法接收一个PerformanceWarning,可以通过这种方式抑制(代码中省略)。

代码

# expand the Yearly records
df1 = df.loc[np.repeat(df.index, df["Plan"].map({"Yearly": 12, "Monthly":1}))]

# compute monthly fee and join date 
df1.loc[df1["Plan"] == "Yearly", "Fee"] /= 12
df1.loc[df1["Plan"] == "Yearly", "Join_Date"] += \
    df1.groupby(["Customer_ID", "Plan"]).cumcount()\
       .loc[df1["Plan"] == "Yearly"]\
       .map(lambda i: pd.DateOffset(months=i))

结果

print(df1)
   Customer_ID     Plan  Join_Date        Fee
0            1   Yearly 2020-01-10  10.000000
0            1   Yearly 2020-02-10  10.000000
0            1   Yearly 2020-03-10  10.000000
0            1   Yearly 2020-04-10  10.000000
0            1   Yearly 2020-05-10  10.000000
0            1   Yearly 2020-06-10  10.000000
0            1   Yearly 2020-07-10  10.000000
0            1   Yearly 2020-08-10  10.000000
0            1   Yearly 2020-09-10  10.000000
0            1   Yearly 2020-10-10  10.000000
0            1   Yearly 2020-11-10  10.000000
0            1   Yearly 2020-12-10  10.000000
1            2  Monthly 2020-01-15  12.000000
2            3  Monthly 2020-02-21  18.000000
3            4   Yearly 2020-02-21   7.166667
3            4   Yearly 2020-03-21   7.166667
3            4   Yearly 2020-04-21   7.166667
3            4   Yearly 2020-05-21   7.166667
3            4   Yearly 2020-06-21   7.166667
3            4   Yearly 2020-07-21   7.166667
3            4   Yearly 2020-08-21   7.166667
3            4   Yearly 2020-09-21   7.166667
3            4   Yearly 2020-10-21   7.166667
3            4   Yearly 2020-11-21   7.166667
3            4   Yearly 2020-12-21   7.166667
3            4   Yearly 2021-01-21   7.166667
4            5   Yearly 2020-03-09  12.000000
4            5   Yearly 2020-04-09  12.000000
4            5   Yearly 2020-05-09  12.000000
4            5   Yearly 2020-06-09  12.000000
4            5   Yearly 2020-07-09  12.000000
4            5   Yearly 2020-08-09  12.000000
4            5   Yearly 2020-09-09  12.000000
4            5   Yearly 2020-10-09  12.000000
4            5   Yearly 2020-11-09  12.000000
4            5   Yearly 2020-12-09  12.000000
4            5   Yearly 2021-01-09  12.000000
4            5   Yearly 2021-02-09  12.000000

推荐阅读