如何在同一数据集的极值两侧拟合直线且不修改原始数据集?
解决方案
核心思路
不用修改原始数据集,通过布尔索引临时筛选极值点左右的样本子集,分别对两个子集做独立线性拟合,而非用全局直线截断区间。具体步骤:
- 完成三阶多项式拟合,计算出turnover frequency(拟合曲线的极值点);
- 用布尔索引从原始数据中提取极值点左侧和右侧的样本;
- 分别对两个子集做一阶多项式(直线)拟合;
- 整合所有拟合结果绘图展示。
代码实现(基于NumPy + Matplotlib)
假设你的原始数据存储在NumPy数组或Pandas DataFrame中,以下是可直接复用的示例:
import numpy as np import matplotlib.pyplot as plt # 替换为你的真实天文观测数据 np.random.seed(42) log_freq = np.linspace(0, 5, 50) log_flux = -0.2*(log_freq - 2.5)**3 + 1.5*(log_freq - 2.5)**2 + np.random.normal(0, 0.3, size=len(log_freq)) # 1. 三阶多项式拟合 poly3_coeffs = np.polyfit(log_freq, log_flux, 3) poly3 = np.poly1d(poly3_coeffs) # 计算turnover frequency:求三阶多项式导数为0的根 poly3_deriv = poly3.deriv() turnover_log_freq = np.roots(poly3_deriv)[0] # 取天文数据中合理的单极值解 # 2. 临时筛选极值点左右的数据集(不修改原始数据) mask_left = log_freq <= turnover_log_freq mask_right = log_freq > turnover_log_freq # 3. 分别拟合左右区间的直线 line_left = np.poly1d(np.polyfit(log_freq[mask_left], log_flux[mask_left], 1)) line_right = np.poly1d(np.polyfit(log_freq[mask_right], log_flux[mask_right], 1)) # 4. 绘图展示 plt.figure(figsize=(10,6)) plt.scatter(log_freq, log_flux, label='Observations', color='k', s=15) plt.plot(log_freq, poly3(log_freq), label='3rd-order Polynomial Fit', color='tab:blue', linewidth=2) plt.plot(log_freq[mask_left], line_left(log_freq[mask_left]), label='Left Linear Fit', color='tab:orange', linestyle='--', linewidth=2) plt.plot(log_freq[mask_right], line_right(log_freq[mask_right]), label='Right Linear Fit', color='tab:green', linestyle='--', linewidth=2) plt.axvline(x=turnover_log_freq, color='r', linestyle=':', label=f'Turnover Frequency (log_freq={turnover_log_freq:.2f})') plt.xlabel('log(Frequency)') plt.ylabel('log(Flux Density)') plt.title('Astronomical Data Fitting: 3rd-order Polynomial + Interval Linear Fits') plt.legend() plt.grid(alpha=0.3) plt.show()
关键细节说明
- 布尔索引的优势:
log_freq[mask_left]只是原始数据的临时子集,不会修改原始数据集的结构或内容; - 极值点准确性:通过三阶多项式的导数求根得到turnover frequency,确保是拟合曲线的真实极值点;
- 区间拟合独立性:左右直线分别基于对应区间的观测数据单独拟合,完全避免了全局直线截断区间的问题。
内容的提问来源于stack exchange,提问作者Jim421616
相关产品推荐
相关产品推荐

