Python中如何将DataFrame指定列拟合为其他列的函数
Python基于Pandas DataFrame实现单/双变量函数拟合
现有真实采集得到的DataFrame实例df,包含两列特征df['X']、df['Y'],以及目标列df['Z'],需要完成两类拟合任务:
- 单变量拟合:
Z = f(X)- 双变量拟合:
Z = f(X,Y)
以下是可直接运行的实现方案,覆盖「无预设函数形式的多项式拟合」和「已知业务规律的自定义非线性拟合」两种最常用场景。
前置依赖导入
import numpy as np from numpy.polynomial import polynomial as P from scipy.optimize import curve_fit
1. 单变量拟合 Z = f(X)
多项式拟合(不知道具体函数形态时首选)
不需要提前假设Z和X的关系,直接通过多项式逼近真实映射,代码简单不需要复杂调参,适合快速探索数据规律:
# 提取有效数据 x = df['X'].values z = df['Z'].values # 自定义多项式阶数,示例用3次多项式:f(X)=a*X³ + b*X² + c*X + d poly_degree = 3 # 拟合得到系数,按常数项、一次项、二次项...从低到高排列 coef_single = P.polyfit(x, z, deg=poly_degree) # 封装可直接调用的预测函数 def f_single(x_input): return P.polyval(np.asarray(x_input), coef_single) # 输出拟合表达式 terms = [] for i in range(len(coef_single)): if i == 0: terms.append(f"{coef_single[i]:.4f}") else: terms.append(f"{coef_single[i]:.4f}*X^{i}") print(f"单变量多项式拟合结果:Z = {' + '.join(terms)}")
自定义非线性函数拟合(已知大致函数关系时用)
如果根据业务经验已经知道Z和X的映射形态(比如指数关系、对数关系),可以自定义函数形式再拟合,结果可解释性更强:
# 示例:假设Z和X满足指数关系 f(X) = a*exp(b*X) + c def custom_single(x, a, b, c): return a * np.exp(b * x) + c # 拟合得到最优参数 popt_single, _ = curve_fit(custom_single, x, z) # 封装预测函数 def f_single_custom(x_input): return custom_single(np.asarray(x_input), *popt_single) # 输出拟合表达式 print(f"单变量自定义函数拟合结果:Z = {popt_single[0]:.4f}*exp({popt_single[1]:.4f}*X) + {popt_single[2]:.4f}")
2. 双变量拟合 Z = f(X,Y)
多项式拟合
二元多项式会自动包含X、Y的独立项和交叉项,同样适合无先验知识时的快速探索,示例用2次二元多项式(形式为f(X,Y)=a + bX + cY + dX² + eXY + fY²):
# 提取有效数据 x = df['X'].values y = df['Y'].values z = df['Z'].values # 构造指定阶数的二元多项式特征 def build_2d_poly(x_arr, y_arr, deg=2): feats = [] feat_names = [] for i in range(deg + 1): for j in range(deg - i + 1): feats.append((x_arr ** i) * (y_arr ** j)) if i == 0 and j == 0: feat_names.append("1") elif i == 0: feat_names.append(f"Y^{j}") elif j == 0: feat_names.append(f"X^{i}") else: feat_names.append(f"X^{i}*Y^{j}") return np.column_stack(feats), feat_names # 生成特征、拟合系数 X_poly, feat_names = build_2d_poly(x, y, deg=2) coef_double, _, _, _ = np.linalg.lstsq(X_poly, z, rcond=None) # 封装预测函数 def f_double(x_input, y_input): input_feats, _ = build_2d_poly(np.asarray(x_input), np.asarray(y_input), deg=2) return input_feats @ coef_double # 输出拟合表达式 terms_double = [f"{coef_double[i]:.4f}*{feat_names[i]}" for i in range(len(coef_double))] print(f"双变量多项式拟合结果:Z = {' + '.join(terms_double)}")
自定义非线性函数拟合
和单变量逻辑一致,自定义包含X、Y的函数形式即可,示例用生产领域常见的幂函数形式f(X,Y)=a*X^b*Y^c:
# 自定义双变量函数,注意X、Y要打包为元组传入 def custom_double(xy, a, b, c): x_val, y_val = xy return a * (x_val ** b) * (y_val ** c) # 拟合最优参数 popt_double, _ = curve_fit(custom_double, (x, y), z) # 封装预测函数 def f_double_custom(x_input, y_input): return custom_double((np.asarray(x_input), np.asarray(y_input)), *popt_double) # 输出拟合表达式 print(f"双变量自定义函数拟合结果:Z = {popt_double[0]:.4f}*X^{popt_double[1]:.4f}*Y^{popt_double[2]:.4f}")
实用注意事项
- 拟合前先清理三列中的缺失值、离群异常值,脏数据会直接导致拟合结果失真
- 多项式阶数不要设置过高,否则会严重过拟合——建议拆分训练集和测试集,选测试集预测误差最小的阶数
- 自定义非线性函数拟合时,最好给
curve_fit传入p0参数设置合理的参数初始值,避免算法收敛到局部最优,得到无意义的结果
内容的提问来源于stack exchange,提问作者SJa
相关产品推荐
相关产品推荐

