在Pandas中使用Lambda函数结合Lmfit拟合DataFrame数据时,如何正确访问行的x值?
在Pandas中结合Lambda和Lmfit时正确传递DataFrame行数据的问题
我来帮你梳理一下问题所在,你遇到的KeyError本质是参数传递顺序搞反了,Lmfit的minimize函数对残差函数的参数顺序有严格要求,咱们一步步来修复:
首先明确核心逻辑:minimize的第一个参数是残差函数,这个函数的第一个参数必须是Lmfit的Parameters对象,剩下的才是你要传入的自定义数据(比如DataFrame的行、拟合用的数组等)。你之前把row放在了残差函数的第一个位置,导致Lmfit把它当成参数对象处理,自然找不到row['x']这个键。
1. 调整残差函数的参数顺序
把Lmfit的参数对象放在第一位,再传入自定义数据,同时处理数据维度匹配问题:
def get_residual(params, row, W_mkin, S): k = 4 # Weibull parameter # 从Lmfit参数对象中取出具体数值 f_mat = params['f_mat'].value W_mmin = params['W_mmin'].value x = row['x'] # 将单个x值扩展为与W_mkin/S同长度的数组,避免维度不匹配报错 x_arr = np.full_like(W_mkin, x) # 转换为numpy数组方便数值运算 W_mkin_np = np.array(W_mkin) S_np = np.array(S) model = 1 - np.exp(-f_mat * x_arr * k * (W_mkin_np - W_mmin)) return S_np - model
2. 修正apply中的参数传递
在lambda里调用minimize时,args只需要传入残差函数除params之外的参数,且顺序要和函数定义一致,同时修正你代码里的列名笔误(W_mkin→Wmkin):
Size_Data['parameters'] = Size_Data.apply(lambda row: minimize(get_residual, params, args=(row, row['Wmkin'], row['S'])), axis=1)
3. 完整修正后的代码
from lmfit import minimize, Parameters import numpy as np import matplotlib.pyplot as plt import pandas as pd # 修正参数顺序的残差函数 def get_residual(params, row, W_mkin, S): k = 4 # Weibull parameter f_mat = params['f_mat'].value W_mmin = params['W_mmin'].value x = row['x'] x_arr = np.full_like(W_mkin, x) W_mkin_np = np.array(W_mkin) S_np = np.array(S) model = 1 - np.exp(-f_mat * x_arr * k * (W_mkin_np - W_mmin)) return S_np - model # 定义拟合参数初始值(给一个更合理的初始值,避免拟合不收敛) params = Parameters() params.add('f_mat', value=0.1) params.add('W_mmin', value=0.05) # 构造DataFrame(修正列名笔误) Size_Data = pd.DataFrame({ 'x': [8e-3, 4e-3], 'Wmkin' : [[0.070247308,0.110537403, 0.150960721, 0.258617823, 0.322579856], [0.100385814, 0.200407372, 0.310034683, 0.440546697, 0.591512151, 0.794210076]], 'S' : [[0.07053083175, 0.3514834285, 0.6014003444, 0.9091664401, 0.9980905768], [0.4077464576, 0.2298558869, 0.5899090607, 0.8002673797, 0.910358319, 0.94841536]] }) # 应用拟合函数到每一行 Size_Data['parameters'] = Size_Data.apply(lambda row: minimize(get_residual, params, args=(row, row['Wmkin'], row['S'])), axis=1) # 查看拟合结果示例 for idx, result in enumerate(Size_Data['parameters']): print(f"第{idx+1}行拟合结果:") print(result.params.pretty_print())
额外提示
- 给参数设置合理初始值(比如把
f_mat设为0.1而非0),能大幅提升拟合收敛概率 - 如果拟合效果不好,可以给参数添加边界约束(比如
params.add('f_mat', value=0.1, min=0)确保参数非负)
内容的提问来源于stack exchange,提问作者Drew Mullaney
相关产品推荐
相关产品推荐

