如何为水果消费DataFrame应用含前一行数据的自定义计算函数?
问题:基于水果消费数据和参数表计算每日利润
数据说明
消费数据spend_df
spend_df Date Apples Pears Grapes 01/01/22 10 47 0 02/01/22 0 22 3 03/01/22 11 0 3 ...
参数表parameters_df
parameters_df Parameter Apples Pears Grapes alpha 132 323 56 beta 424 31 33 theta 13 244 323
目标利润表profit_df
需应用公式 y = beta*(1 - exp(-(theta*previous + current)/alpha)) 计算每日利润(previous为前一日消费额,current为当日消费额),最终生成:
profit_df Date Apples Pears Grapes 01/01/22 30.93 4.19 0 02/01/22 265.63 31.00 1.72 03/01/22 33.90 30.99 32.99 ...
错误代码尝试
# First map parameters_df to spend_df merged_df = input_df.merge(parameters_df, on=['Apples','Pears','Grapes']) # Apply function to each row profit_df = merged_df.apply(lambda x: beta(1 - exp(-(theta*x[-1] + x)/alpha))
解决方案
你的代码存在几个核心问题:
- 合并逻辑错误:用消费列作为merge的关联键完全不符合需求,参数表是按水果对应固定参数,不需要和消费表合并。
- 缺少前一日数据:公式依赖前一日消费额,未对数据做滞后处理。
- 变量引用无效:直接用
beta/theta/alpha这些变量名,Python无法识别对应参数值。 - 语法不完整:lambda表达式未闭合括号,且未导入
exp函数。
修正后的代码
import numpy as np import pandas as pd # 假设spend_df和parameters_df已加载完成 # 1. 转置参数表,方便按水果提取参数 params = parameters_df.set_index('Parameter').T # 2. 生成前一日消费数据,第一日无历史数据,用0填充 spend_with_prev = spend_df.copy() for fruit in ['Apples', 'Pears', 'Grapes']: spend_with_prev[f'{fruit}_prev'] = spend_with_prev[fruit].shift(1).fillna(0) # 3. 定义利润计算函数 def calc_profit(row, fruit): alpha = params.loc[fruit, 'alpha'] beta = params.loc[fruit, 'beta'] theta = params.loc[fruit, 'theta'] current = row[fruit] previous = row[f'{fruit}_prev'] # 当日和前一日都为0时利润为0 if current == 0 and previous == 0: return 0.0 return beta * (1 - np.exp(-(theta * previous + current) / alpha)) # 4. 计算每种水果的利润并格式化 profit_df = spend_df[['Date']].copy() for fruit in ['Apples', 'Pears', 'Grapes']: profit_df[fruit] = spend_with_prev.apply(lambda r: calc_profit(r, fruit), axis=1) profit_df[fruit] = profit_df[fruit].round(2) print(profit_df)
代码说明
- 转置参数表后,可直接通过水果名称提取对应的
alpha/beta/theta值。 - 用
shift(1)获取前一日消费数据,第一日的滞后值用0填充,匹配示例中的计算逻辑。 - 单独定义计算函数,避免lambda表达式过于复杂,可读性更强。
- 对结果保留两位小数,和目标表格式一致。
内容的提问来源于stack exchange,提问作者star_it8293
相关产品推荐
相关产品推荐

