【问题标题】:Python SciPy UnivariateSpline vs R smooth.splinePython SciPy UnivariateSpline vs R smooth.spline
【发布时间】:2019-11-02 04:37:39
【问题描述】:

我正在将用 R 编写的脚本移植到 Python。在 R 中,我使用的是 smooth.spline,而在 Python 中,我使用的是 SciPy UnivariateSpline。它们不会产生相同的结果(即使它们都基于三次样条方法)。有没有办法或替代 UnivariateSpline 使 Python 样条返回与 R 相同的样条?

我是一名数学家。我了解样条线的一般概念。但不是它们在 Python 或 R 中实现的细节。

这是 R 中的代码,然后是 Python。两者的输入数据相同。

这是输入数据:

x =  0.0,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9,  1.0
y =   -1,    1,    1,   -1,    1,    0,   .5,   .5,   .4,   .5,   -1

这里是R代码

x = seq(0,1, by = .1); 
y = c(-1,1,1, -1,1,0, .5,.5,.4,  .5, -1);
spline_xy = smooth.spline(x,y)
predict(spline_xy,x)

哪个输出:

$x
 [1] 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0

$y
 [1]  0.120614583  0.170800975  0.210954680  0.238032338  0.253672155
 [6]  0.253684815  0.236432643  0.200264536  0.145403302  0.074993797
[11] -0.004853825

这是 Python 代码

import numpy as np
from scipy.interpolate import UnivariateSpline
x = np.linspace(0, 1, num = 11, endpoint=True)    
y = np.array([-1,1,1, -1,1,0, .5,.5,.4,  .5, -1]) 
spline_xy = UnivariateSpline(x,y)
print('x =', x)
print('ysplined =',spline_xy(x))

哪个输出:

x = [0.  0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1. ]

ysplined = 
[-0.26433566 -0.02587413  0.18857809 0.36585082  0.49277389  
  0.55617716 0.54289044  0.43974359  0.23356643 -0.08881119 
 -0.54055944]

我希望 R $y 和 Python ysplined 中的输出是相同的。但他们不是。

任何帮助,例如如何设置参数,或解释将不胜感激!提前谢谢你。

【问题讨论】:

    标签: python r scipy spline


    【解决方案1】:

    您可以在 Python 中通过 rpy2 使用 R 函数:

    import numpy as np
    import rpy2.robjects as robjects
    x = np.linspace(0, 1, num = 11, endpoint=True)    
    y = np.array([-1,1,1, -1,1,0, .5,.5,.4,  .5, -1])
    
    r_x = robjects.FloatVector(x)
    r_y = robjects.FloatVector(y)
    r_smooth_spline = robjects.r['smooth.spline'] #extract R function
    spline_xy = r_smooth_spline(x=r_x, y=r_y)
    print('x =', x)
    print('ysplined =',np.array(robjects.r['predict'](spline_xy,robjects.FloatVector(x)).rx2('y')))
    

    哪个输出:

    x = [0.  0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1. ]
    ysplined = [ 0.12061458  0.17080098  0.21095468  0.23803234  0.25367215  0.25368481
    0.23643264  0.20026454  0.1454033   0.0749938  -0.00485382]
    

    如你所愿。

    如果要直接设置lambdaspline_xy = r_smooth_spline(x=r_x, y=r_y, lambda=42)不行,因为lambda在Python中已经有别的意思了,但是有一个解决办法:How to use the lambda argument of smooth.spline in RPy WITHOUT Python interprating it as lambda

    【讨论】:

      【解决方案2】:

      在我看来,这些是不同的平滑方法。

      smooth.spline 在 R 中是一个“平滑样条”,它是一个过度参数化的自然样条(每个数据点的结,内部的三次样条,线性外推),使用惩罚最小二乘法来选择参数。您可以阅读帮助页面了解如何计算罚分的详细信息。

      另一方面,Python 的 UnivariateSpline 出现在此处的文档中: https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.UnivariateSpline.html 是回归样条,由最小二乘拟合,没有惩罚。它似乎可以自适应地选择结数。

      这些是完全不同的算法,我不希望它们给出相同的结果。 我不知道是否有一个 R 包使用与 Python 相同的自适应节点选择。这个答案:https://stackoverflow.com/a/55481248/2554330 声称引用 Python 中的自然平滑样条实现,但我不知道它是否与 R 的实现匹配。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-01-06
        • 2013-07-28
        • 1970-01-01
        • 1970-01-01
        • 2020-01-06
        • 1970-01-01
        • 1970-01-01
        • 2015-06-01
        相关资源
        最近更新 更多