繁体   English   中英

将R中的曲线拟合到方程

[英]Fitting a curve in R to an equation

我一直在尝试在R上拟合曲线,但是有一些问题。 我正在处理组成x和y坐标的几个大数据集。 当使用ggplot的geom_point或任何其他绘图函数进行绘图时,存在一种趋势,该绘图趋于类似于平方根函数的图。

这将是使用我使用的geom_smooth进行拟合的代码:

plt = ggplot(data = data2, aes(x = x, y = y)) + geom_point() +geom_smooth()

这基本上让我明白了这一点:

曲线图

有没有一种方法可以使曲线更像红色平方根曲线(y = x ^ 0.5)-基本上使它更平滑并相应地适合某个公式? 以最小的数据集为例。

数据集CSV格式示例

我也尝试过将方法拟合为黄土,这使曲线接近我想要的,但对于更大(约500,000-700,000点)或某些点非常密集地封装在某些点中的数据集区域黄土似乎不起作用。 均值存在某种偏斜的趋势,这是有道理的,因为该区域的大量点将其推高了。 但是我需要拟合曲线并迫使其接近平方根曲线。 我也尝试过弄乱跨度值,但这并没有真正影响曲线的平滑度。

我想到的一件事是以下内容。 最好的图形可能是通过最小化卡方来评估的。 您可以对此附加标准,即,该拟合度与平方根行为的偏离量为多少。 这可以通过使用sqrt()拟合解决方案并将加权卡方平方添加到对拟合质量的总体评估中来完成。 不知道如何执行R ,但是在python中,您得到的是这样的: 增加sqrt的重量 蓝色图将是最合适的sqrt() 黄色的是最好的二次样条,其结点为[0,0,.1,.2,.3,.4,.6,.9,.9,.9] ,即weight=0 (您还可以优化结位置,在此不做)。 然后,我们增加权重以通过sqrt()分别拟合weights = 0.5,1,2weights = 0.5,1,2分别weights = 0.5,1,2

代码如下:

import matplotlib
matplotlib.use('Qt4Agg')

from matplotlib import pyplot as plt
import numpy as np
from scipy.optimize import leastsq,curve_fit

###from the scipy doc page as I have scipy 0.16 and no build in BSpline, yet
def B(x, k, i, t):
    if k == 0:
        return 1.0 if t[i] <= x < t[i+1] else 0.0
    if t[i+k] == t[i]:
        c1 = 0.0
    else:
        c1 = (x - t[i])/(t[i+k] - t[i]) * B(x, k-1, i, t)
    if t[i+k+1] == t[i+1]:
        c2 = 0.0
    else:
        c2 = (t[i+k+1] - x)/(t[i+k+1] - t[i+1]) * B(x, k-1, i+1, t)
    return c1 + c2


def bspline(x, t, c, k):
    n = len(t) - k - 1
    assert (n >= k+1) and (len(c) >= n)
    return sum(c[i] * B(x, k, i, t) for i in range(n))


def mixed_res(params,points,weight):
    [xList,yList] = zip(*points)
    bSplList=[bspline(x,[0,0,.1,.2,.3,.4,.6,.9,.9,.9],params,2) for x in xList]
    ###standard chisq
    diffTrue=[y-b for y,b in zip(yList,bSplList)]
    ###how good can the spline be fitted with sqrt
    locfit,_=curve_fit(sqrtfunc,xList,bSplList)
    sqrtList=[sqrtfunc(x,locfit[0]) for x in xList]
    diffWeight=[ weight*(s-b) for s,b in zip(sqrtList,bSplList)]
    return diffTrue+diffWeight

def sqrtfunc(x,a):
    return a*np.sqrt(x)


xList,yList=np.loadtxt("PHOQSTACK.csv", unpack=True, delimiter=',')
xListSorted=sorted(xList)
zipData=zip(xList,yList)

fig=plt.figure(1)
ax=fig.add_subplot(1,1,1)

knotList=[0,0,.1,.2,.3,.4,.6,.9,.9,.9]
order=2

sqrtvalues,_=curve_fit(sqrtfunc,xList,yList)
th_sqrt_y=[sqrtfunc(x,sqrtvalues[0]) for x in xListSorted]

ax.scatter(xList,yList,s=1)
ax.plot(xListSorted,th_sqrt_y)

fitVals=[.2,.3,.4,.2,.3,.4,.2]
for s in [0,.5,1,2]:
    print s
    fitVals,ier=leastsq(mixed_res,fitVals,args=( zipData, s ) )
    th_b_y=[bspline(x,knotList,fitVals,order) for x in xListSorted]
    ax.plot(xListSorted,th_b_y)

plt.show()

问题在于,对于较大的权重,拟合要比将实际数据拟合sqrt更多的时间将其转换为sqrt ,您可能会遇到收敛问题。

第二种选择是直接使sqrt成为拟合的一部分,并提供其相对贡献作为卡方的一部分。 包括sqrt 与以前一样,蓝色和黄色图形。 其他均采用与上述相同的权重进行拟合。

为此,我将残差函数更改为

def mixed_res(params,points,weight):
    a=params[0]
    coffs=params[1:]
    [xList,yList] = zip(*points)
    sqrtList=[a*np.sqrt(x) for x in xList]
    bSplList=[bspline(x,[0,0,.1,.2,.3,.4,.6,.9,.9,.9],coffs,2) for x in xList]
    diffTrue=[y-s-b for y,s,b in zip(yList,sqrtList,bSplList)]
    diffWeight=[ weight*(s-b)/(s+.001) for s,b in zip(sqrtList,bSplList)]

    return diffTrue+diffWeight

并呼吁适合

fitVals=[.4]+[.2,.3,.4,.2,.3,.4,.4]
for s in [0,.5,1,2]:
    print s
    fitVals,ier=leastsq(mixed_res,fitVals,args=( zipData, s ) )
    th_b_y=[fitVals[0]*np.sqrt(x)+bspline(x,knotList,fitVals[1:],order) for x in xListSorted]
    ax.plot(xListSorted,th_b_y)

剩下的大问题是:您如何确定要采用的权重? 更像平方根是什么意思?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM