You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python的patsy中实现自由度为2的自然样条?

在patsy中实现自由度为2的自然样条(对应R的ns(x, df=2))

背景

R语言的ns()函数支持直接设置自由度为2的自然样条,示例代码:

x <- 0:10
y <- x**2
lm(y ~ ns(x, df=2))

但Python中patsy库的cr()函数要求自由度≥3,无法直接实现相同效果。

解决方案

自由度为2的自然样条本质上等价于线性拟合(自然样条在df=2时,约束边界二阶导数为0,最终拟合结果就是一条直线),因此有两种实现方式:

方法1:直接用线性项替代(最简方案)

直接使用x的线性项即可完全匹配R中ns(x, df=2)的拟合结果:

import numpy as np
import pandas as pd
import statsmodels.formula.api as smf

# 构造数据集
df = pd.DataFrame({
    "x": np.arange(11),
    "y": np.arange(11)**2
})

# 公式直接使用线性项
formula = "y ~ x"
reg = smf.ols(formula, data=df).fit()
print(reg.summary())

方法2:自定义patsy转换函数(保持样条写法)

如果需要在公式中保留类似R的样条函数调用形式,可以自定义一个ns2转换函数,手动构造自由度为2的自然样条基:

import numpy as np
import pandas as pd
import statsmodels.formula.api as smf
from patsy import user_transform
from scipy.interpolate import BSpline

@user_transform
def ns2(x):
    # 构造自然样条基:df=2对应一次多项式,满足边界二阶导数为0的约束
    x_min, x_max = x.min(), x.max()
    # 自然样条节点:边界节点重复3次以满足边界条件
    knots = np.array([x_min, x_min, x_min, x_max, x_max, x_max])
    # 生成自由度为2的样条基
    basis = BSpline(knots, np.eye(2), k=1)(x)
    return basis

# 在公式中使用自定义的ns2函数
formula = "y ~ ns2(x)"
reg = smf.ols(formula, data=df).fit()
print(reg.summary())

说明

两种方法的拟合结果完全一致,都等价于R中ns(x, df=2)的输出。如果仅需实现功能,推荐方法1;如果需要统一代码风格(保持样条函数调用形式),可以使用方法2。

内容的提问来源于stack exchange,提问作者EuginePickett

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 10:25:25