Pandas中如何实现指数拟合并将拟合结果新增为数据列
问题描述
现有如下数据集:
import pandas as pd import numpy as np puf = pd.DataFrame({'id':[1,2,3,4,5,6,7,8], 'val':[850,1889,3289,6083,10349,17860,28180,41236]})
该数据符合指数曲线分布,可通过如下代码绘制原始趋势图:
puf.plot('id','val')

需求为拟合形如 $y = Ae^{Bx}$(即A乘以e的Bx次方)的指数曲线,将逐行对应的拟合结果作为新列存入Pandas DataFrame。
初始实现思路为先对val列取自然对数,再调用Numpy接口拟合方程:
puf['log_val'] = np.log(puf['val']) puf['fit'] = np.polyfit(puf['id'],puf['log_val'],1)
执行时抛出如下错误:
ValueError: Length of values (2) does not match length of index (8)
预期输出为逐行对应的指数拟合值列,拟合效果参考:
报错原因
np.polyfit 执行1阶(线性)拟合时,返回值是长度为2的系数数组,依次对应拟合直线的斜率、截距,本身不返回逐点的预测结果。将长度为2的数组直接赋值给长度为8的DataFrame列,必然触发长度不匹配的报错。
正确实现方法
按以下步骤操作即可:
- 对目标y值做自然对数转换后执行线性拟合,拿到线性方程的两个系数
- 将线性系数转换为指数方程参数:拟合得到的斜率就是公式中的B,截距取自然指数就是参数A
- 代入指数公式逐行计算每个id对应的拟合值,存入新列
完整可运行代码:
# 对数转换后拟合线性方程,拿到斜率B、截距ln_A B, ln_A = np.polyfit(puf['id'], np.log(puf['val']), deg=1) A = np.exp(ln_A) # 逐行计算指数拟合值 puf['fit'] = A * np.exp(B * puf['id'])
如果需要更高的拟合精度,可以跳过对数转换步骤,直接用非线性最小二乘法拟合,避免对数转换带来的误差,示例如下:
from scipy.optimize import curve_fit # 定义指数函数形式 def exp_func(x, A, B): return A * np.exp(B * x) # 拟合并计算预测值 popt, _ = curve_fit(exp_func, puf['id'], puf['val'], p0=[1, 0.5]) puf['fit_nonlinear'] = exp_func(puf['id'], *popt)
内容的提问来源于stack exchange,提问作者Alexis
相关产品推荐
相关产品推荐

