如何为散点图拟合适配高密区域的单一多项式曲线
解决方案
核心原因
你当前用np.polyfit默认做的是普通最小二乘拟合,会平等对待所有输入样本的残差,因此稀疏的低星等区域样本会把拟合曲线拉偏,无法贴合密集区间的趋势。
调整方案
这里提供两种实现方式,你可以按需选择:
方案1:加权最小二乘拟合(推荐)
给-1.75~-1.5密集区间的样本分配更高权重,降低边缘区域样本的影响,既保留整体趋势又优先贴合密集区:
from sklearn.mixture import GaussianMixture from sklearn import preprocessing import numpy as np import matplotlib.pyplot as plt import pandas as pd from scipy import stats from astropy.io import ascii from scipy.stats import norm import math from sklearn.metrics import r2_score data2 = pd.read_csv("Dispersion total.csv") names = data2.columns df = pd.DataFrame(data2, columns=names) data3 = pd.read_csv("Dispersion less than equal to -1.5.csv") names1 = data3.columns df1 = pd.DataFrame(data3, columns=names1) x= df1['Mean Mag'].values y=df1['Log(sigma)'].values w= df['Mean Mag'].values z=df['Log(sigma)'].values # --- 新增:定义样本权重 --- # 方式A:硬权重,密集区间权重是其他区域的10倍 weights = np.where((x >= -1.75) & (x <= -1.5), 10, 1) # 方式B:平滑高斯权重,更自然的渐变权重,可替换上面一行 # weights = np.exp(-(x + 1.625)**2 / (2 * 0.125**2)) # 加权多项式拟合 fit = np.polyfit(x, y, 2, w=weights) a, b, c = fit # 生成排序的x点用于绘制顺滑曲线 x_plot = np.linspace(x.min(), x.max(), 100) fit_equation = a * np.square(x_plot) + b * x_plot + c #Plotting fig1 = plt.figure() ax1 = fig1.subplots() ax1.plot(x_plot, fit_equation,color = 'r',alpha = 0.5, label = 'Weighted polynomial fit') ax1.scatter(w,z, s = 4, color = 'b', label = 'Data points') ax1.set_title('Polynomial fit example') ax1.legend() plt.xlabel('Mean Magnitude') plt.ylabel('Log(sigma)') plt.show()
方案2:直接用密集区间样本拟合
如果不需要考虑边缘区域的影响,直接截取-1.75~-1.5区间的样本做拟合即可:
# 仅截取密集区间样本参与拟合 mask = (x >= -1.75) & (x <= -1.5) x_fit = x[mask] y_fit = y[mask] fit = np.polyfit(x_fit, y_fit, 2) a, b, c = fit x_plot = np.linspace(x.min(), x.max(), 100) fit_equation = a * np.square(x_plot) + b * x_plot + c # 后续绘图代码和方案1一致即可
额外优化
原代码直接用原始x数组绘制拟合曲线,若x未排序会导致曲线错乱,上述代码新增了x_plot生成连续排序的采样点,保证曲线顺滑。
内容的提问来源于stack exchange,提问作者Arghya Chakraborty
相关产品推荐
相关产品推荐

