R语言bs()样条函数生成B样条基矩阵的Python等价实现方法查询
R中
splines::bs生成B样条基矩阵的Python等价实现 你之前直接调用scipy.interpolate.BSpline类无法生成基矩阵,是因为该类默认用于拟合完成后的样条预测,我们可以通过以下两种方案实现和R一致的基矩阵生成逻辑,仅需传入输入数组、内部节点、阶数三个参数即可。
方案1:基于scipy原生实现(无需额外安装第三方库)
核心逻辑是手动构造R的bs函数默认的钳位节点序列,再调用BSpline的静态方法计算每个基函数的取值,最终拼接为基矩阵:
import numpy as np from scipy.interpolate import BSpline def get_bspline_basis(x, internal_knots, degree): # 构造完整节点序列:首尾各加degree个和x边界值一致的节点 x_min, x_max = x.min(), x.max() full_knots = np.concatenate([ [x_min]*degree, internal_knots, [x_max]*degree ]) # 基函数总数 = 内部节点数 + 阶数 n_basis = len(internal_knots) + degree basis_mat = np.zeros((len(x), n_basis)) # 逐个生成每个基函数的取值 for i in range(n_basis): knots_i = full_knots[i:i+degree+2] basis = BSpline.basis_element(knots_i, extrapolate=False) basis_mat[:, i] = basis(x) # 边界外的空值补0,和R的bs行为完全对齐 basis_mat = np.nan_to_num(basis_mat, nan=0.0) return basis_mat # 样例测试 women_height = np.array([58,59,60,61,62,63,64,65,66,67,68,69,70,71,72]) knots = np.array([59.4, 62.2, 65. , 67.8, 70.6]) degree = 3 bs_mat = get_bspline_basis(women_height, knots, degree) print(bs_mat)
方案2:基于patsy库实现(和Rsplines::bs行为100%兼容)
patsy是Python中专门用于统计模型公式解析的库,内置的bs函数参数、输出逻辑和R完全一致,使用更简便:
- 先安装依赖:
pip install patsy - 调用代码:
import numpy as np from patsy import bs women_height = np.array([58,59,60,61,62,63,64,65,66,67,68,69,70,71,72]) knots = np.array([59.4, 62.2, 65. , 67.8, 70.6]) degree = 3 # 直接生成基矩阵,参数规则和R完全一致 bs_mat = bs(women_height, knots=knots, degree=degree, include_intercept=False) print(bs_mat)
如果需要生成包含截距项的基矩阵,仅需将include_intercept参数设为True即可。
内容的提问来源于stack exchange,提问作者ignoring_gravity
相关产品推荐
相关产品推荐

