我无法在数据中拟合一条平均曲线以找到长度。在一个大熊猫数据框中,我有很多X,Y点,看起来像:
x = np.asarray([731501.13, 731430.24, 731360.29, 731289.36, 731909.72, 731827.89,
731742. , 731657.74, 731577.95, 731502.64, 731430.39, 731359.12,
731287.3 , 731214.21, 732015.59, 731966.88, 731902.67, 731826.31,
731743.79, 731660.94, 731581.29, 731505.4 , 731431.95, 732048.71,
732026.66, 731995.46, 731952.18, 731894.29, 731823.58, 731745.16,
732149.61, 732091.53, 732052.98, 732026.82, 732005.17, 731977.63,
732691.84, 732596.62, 732499.45, 732401.62, 732306.18, 732218.35,
732141.82, 732080.91, 732038.21, 732009.08, 733023.08, 732951.99,
732873.32, 732787.51])
y = np.asarray([7873771.69, 7873705.34, 7873638.03, 7873571.73, 7874082.33,
7874027.2 , 7873976.22, 7873923.58, 7873866.35, 7873804.53,
7873739.58, 7873673.62, 7873608.23, 7873544.15, 7874286.21,
7874197.15, 7874123.96, 7874063.21, 7874008.78, 7873954.69,
7873897.31, 7873836.09, 7873772.38, 7874564.62, 7874448.23,
7874341.23, 7874246.59, 7874166.93, 7874100.4 , 7874041.77,
7874912.56, 7874833.09, 7874733.62, 7874621.43, 7874504.65,
7874393.89, 7875225.26, 7875183.85, 7875144.42, 7875105.69,
7875064.49, 7875015.5 , 7874954.94, 7874878.36, 7874783.13,
7874674. , 7875476.18, 7875410.05, 7875351.67, 7875300.61])
x和y是地图视图的坐标,我想计算长度。我可以编码欧几里德距离,但是由于这些点是分散的并且不是一个接一个的点,因此在尝试通过该点拟合移动线时遇到了麻烦。我已经尝试过polyfit,但是即使度数较高,也可以产生一条直线,例如:
from numpy.polynomial.polynomial import polyfit
import numpy as np
import matplotlib.pyplot as plt
z = np.polyfit(x,y,10)
p = np.poly1d(z)
plt.scatter(x,y, marker='x')
plt.scatter(x, p(x), marker='.')
plt.show()
这是为了证明我的意思1
任何帮助将不胜感激!
答案 0 :(得分:2)
这将是适合您数据的经验函数:
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
x = np.asarray([731501.13, 731430.24, 731360.29, 731289.36, 731909.72, 731827.89,
731742. , 731657.74, 731577.95, 731502.64, 731430.39, 731359.12,
731287.3 , 731214.21, 732015.59, 731966.88, 731902.67, 731826.31,
731743.79, 731660.94, 731581.29, 731505.4 , 731431.95, 732048.71,
732026.66, 731995.46, 731952.18, 731894.29, 731823.58, 731745.16,
732149.61, 732091.53, 732052.98, 732026.82, 732005.17, 731977.63,
732691.84, 732596.62, 732499.45, 732401.62, 732306.18, 732218.35,
732141.82, 732080.91, 732038.21, 732009.08, 733023.08, 732951.99,
732873.32, 732787.51])/732 -1000
y = np.asarray([7873771.69, 7873705.34, 7873638.03, 7873571.73, 7874082.33,
7874027.2 , 7873976.22, 7873923.58, 7873866.35, 7873804.53,
7873739.58, 7873673.62, 7873608.23, 7873544.15, 7874286.21,
7874197.15, 7874123.96, 7874063.21, 7874008.78, 7873954.69,
7873897.31, 7873836.09, 7873772.38, 7874564.62, 7874448.23,
7874341.23, 7874246.59, 7874166.93, 7874100.4 , 7874041.77,
7874912.56, 7874833.09, 7874733.62, 7874621.43, 7874504.65,
7874393.89, 7875225.26, 7875183.85, 7875144.42, 7875105.69,
7875064.49, 7875015.5 , 7874954.94, 7874878.36, 7874783.13,
7874674. , 7875476.18, 7875410.05, 7875351.67, 7875300.61])/7873 - 1000
def my_func( x, x0, y0, a, b, c, t, s):
xs = x-x0
p = a * xs**3 + b * xs**2 + c * xs + y0
t = t * np.tanh( s * xs )
return p + t
xth = np.linspace( -1.15, 1.5, 50 )
yth = my_func( xth, 0.03, 0.18, .01, 0, 0.05, .05 , 10)
sol, err = curve_fit( my_func, x, y, p0=[0.03, 0.18, .01, 0, 0.05, .05 , 10] )
print sol
fig = plt.figure()
ax = fig.add_subplot( 1, 1, 1 )
ax.scatter( x, y )
ax.plot( xth, yth )
ax.plot( xth, my_func( xth, *sol) )
plt.show()
给予
>>[ 2.86281016e-02 1.95292660e-01 9.62290944e-03 -1.26304655e-02 5.11281073e-02 4.63955967e-02 1.02260568e+01]
和
答案 1 :(得分:1)
这是我锤几个小时后想到的。首先,我观察到大约两个数据区域,即数据范围的下半部分和上半部分,每半部分都有不同的特性。上半部分比较平坦,数据点较少,下半部分则有较大的曲率,只有几组几乎重叠的数据点。下面是我尝试将这两个区域分别建模为该问题的第一个切入点。我包括一个“缩放”图,该图显示了不相交的重叠区域,这使得此代码在目前的形式上无法令人满意。我有信心可以再坚持一两天,使它变得更好,但是这种解决方案可能不是您所需要的。
import numpy
import matplotlib
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
cutoffVal = 732200.0 # x below or above this value
xData = numpy.asarray([731501.13, 731430.24, 731360.29, 731289.36, 731909.72, 731827.89,
731742, 731657.74, 731577.95, 731502.64, 731430.39, 731359.12,
731287.3, 731214.21, 732015.59, 731966.88, 731902.67, 731826.31,
731743.79, 731660.94, 731581.29, 731505.4, 731431.95, 732048.71,
732026.66, 731995.46, 731952.18, 731894.29, 731823.58, 731745.16,
732149.61, 732091.53, 732052.98, 732026.82, 732005.17, 731977.63,
732691.84, 732596.62, 732499.45, 732401.62, 732306.18, 732218.35,
732141.82, 732080.91, 732038.21, 732009.08, 733023.08, 732951.99,
732873.32, 732787.51])
yData = numpy.asarray([7873771.69, 7873705.34, 7873638.03, 7873571.73, 7874082.33,
7874027.2, 7873976.22, 7873923.58, 7873866.35, 7873804.53,
7873739.58, 7873673.62, 7873608.23, 7873544.15, 7874286.21,
7874197.15, 7874123.96, 7874063.21, 7874008.78, 7873954.69,
7873897.31, 7873836.09, 7873772.38, 7874564.62, 7874448.23,
7874341.23, 7874246.59, 7874166.93, 7874100.4, 7874041.77,
7874912.56, 7874833.09, 7874733.62, 7874621.43, 7874504.65,
7874393.89, 7875225.26, 7875183.85, 7875144.42, 7875105.69,
7875064.49, 7875015.5, 7874954.94, 7874878.36, 7874783.13,
7874674. , 7875476.18, 7875410.05, 7875351.67, 7875300.61])
# split off data into above and below cutoff
xAboveList = []
yAboveList = []
xBelowList = []
yBelowList = []
for i in range(len(xData)):
if xData[i] > cutoffVal:
xAboveList.append(xData[i])
yAboveList.append(yData[i])
else:
xBelowList.append(xData[i])
yBelowList.append(yData[i])
xAbove = numpy.array(xAboveList)
xBelow = numpy.array(xBelowList)
yAbove = numpy.array(yAboveList)
yBelow = numpy.array(yBelowList)
# to fit for data above the cutoff value use a quadratic logarithmic equation
def aboveFunc(x, a, b, c):
return a + b*numpy.log(x) + c*numpy.power(numpy.log(x), 2.0)
# to fit for data below the cutoff value use a hyperbolic type with offset
def belowFunc(x, a, b, c):
val = x - cutoffVal
return val / (a + (b * val) - ((a + b) * val * val)) + c
# some initial parameter values
initialParameters_above = numpy.array([1.0, 1.0, 1.0])
initialParameters_below = numpy.array([-4.29E-04, 4.31E-04, 7.87E+06])
# curve fit the equations individually to their respective data
aboveParameters, pcov = curve_fit(aboveFunc, xAbove, yAbove, initialParameters_above)
belowParameters, pcov = curve_fit(belowFunc, xBelow, yBelow, initialParameters_below)
# for plotting the fitting results
xModelAbove = numpy.linspace(max(xBelow), max(xAbove))
xModelBelow = numpy.linspace(min(xBelow), max(xBelow))
y_fitAbove = aboveFunc(xModelAbove, *aboveParameters)
y_fitBelow = belowFunc(xModelBelow, *belowParameters)
plt.plot(xData, yData, 'D') # plot the raw data as a scatterplot
plt.plot(xModelAbove, y_fitAbove) # plot the above equation using the fitted parameters
plt.plot(xModelBelow, y_fitBelow) # plot the below equation using the fitted parameters
plt.show()
print('Above parameters:', aboveParameters)
print('Below parameters:', belowParameters)