我有代码从 CDF 插入样条线,该样条线在范围 x=40 和 x=110 之间似乎有效。低于 40,我想要一条在 0 处的平坦线,在 110 之后,一条在 1 处朝向无穷大的平坦线。
我想出了这段代码:
def _find_spline(x_orig: np.ndarray, cdf: np.ndarray) -> BSpline:
# Find the smoothing factor
smoothing_factor, iters = _find_highest_smoothing_factor(x_orig, cdf, 1e-5)
# Fit a linear spline to the first segment
t_begin, c_begin, k_begin = splrep([0, x_orig[0]], [0, cdf[0]], k=1)
# Fit the middle segment with the specified smoothing factor
t_middle, c_middle, k_middle = splrep(x_orig, cdf, s=smoothing_factor)
# Explicitly construct the final segment
t_end = np.array([x_orig[-1], x_orig[-1], 300, 300]) # Linear knots
c_end = np.array([cdf[-1], 1.0]) # Start from the evaluated value
# Combine the knots and coefficients
t_combined = np.concatenate([t_begin[:-1], t_middle[1:-1], t_end])
c_combined = np.concatenate([c_begin[:-1], c_middle[1:-1], c_end])
return BSpline(t_combined, c_combined, k_middle, extrapolate=True)
我已经上传了完整的可重现示例here。
但是,这会生成类似以下内容:
所以,直到 40 之前的第一段看起来都很好,并且计算结果为 0...但我不知道为什么样条线在 110 结束时下降到 0,我希望它继续直线...
出了什么问题?
你不能仅仅通过不断的外推来脱离样条线构造,你必须自己实现它(除非线性插值可以,在这种情况下你只需使用
np.interp
)。
有几种实现方式:
事实上,我更推荐后一种方法。 这个 scipy 页面有几个示例(它以
interp1d
示例开头,非常不再推荐;其他的都是相关的):
https://docs.scipy.org/doc/scipy/tutorial/interpolate/extrapolation_examples.html