如何将年度订阅费用拆分为月度数据?求替代重采样的方法
解决年度订阅费用拆分到月度的问题
嘿,我来帮你搞定这个订阅费用拆分的需求!你想要把年度订阅的年费平摊到每个月,同时保留月度订阅的原始记录对吧?咱们一步步来解决这个问题,先看看你之前代码的问题,再给出可行的方案。
先说说你之前代码的问题
你写的atom函数里,直接用df.Plan=='Yearly'是对整个DataFrame的列做判断,不是针对当前行的,这会导致逻辑错误;另外用groupby + apply的方式不太适合生成多行的扩展记录,因为这种写法通常是对每组返回一个聚合结果,而不是把一行拆成多行。
可行的解决方案:拆分年度订阅为月度记录
我们可以通过为每个年度订阅行生成12条月度记录,同时保留月度订阅的单行记录来实现需求。具体代码如下:
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']) # 定义处理每行订阅记录的函数 def expand_subscription(row): if row['Plan'] == 'Yearly': # 生成从订阅当月第一天开始的12个连续月份(月初日期) subscription_months = pd.date_range( start=row['Join_Date'].replace(day=1), periods=12, freq='MS' ) # 计算平摊后的月度费用 monthly_cost = row['Fee'] / 12 # 返回该年度订阅对应的12条月度记录 return pd.DataFrame({ 'Customer_ID': [row['Customer_ID']] * 12, 'Plan': ['Yearly'] * 12, 'Billing_Month': subscription_months, 'Monthly_Fee': [monthly_cost] * 12 }) else: # 月度订阅直接返回当月的记录 return pd.DataFrame({ 'Customer_ID': [row['Customer_ID']], 'Plan': [row['Plan']], 'Billing_Month': [row['Join_Date'].replace(day=1)], 'Monthly_Fee': [row['Fee']] }) # 应用函数并合并所有结果 final_df = pd.concat(df.apply(expand_subscription, axis=1).tolist(), ignore_index=True) # 查看结果 print(final_df.head(15))
代码说明
- 对于年度订阅:用
pd.date_range生成从订阅当月第一天开始的12个连续月份(freq='MS'表示每个月的第一天),确保覆盖整个订阅周期的每个自然月;然后将年费除以12得到每月平摊费用,为每个月份生成一条记录。 - 对于月度订阅:直接保留当月的记录,费用就是原始的月度订阅费。
- 最后用
pd.concat把所有行生成的小DataFrame合并成最终的完整表格。
可选:只保留订阅当年的月份
如果你只需要拆分到订阅开始年份的月份(比如客户1只需要2020年1-12月的记录,而不是包含2021年1月),可以在生成月份后加一个过滤:
# 只保留订阅开始年份的月份 subscription_months = subscription_months[subscription_months.year == row['Join_Date'].year]
这样就能精准得到你想要的年度内月度拆分结果啦!
内容的提问来源于stack exchange,提问作者Sp_95
相关产品推荐
相关产品推荐

