Кривая примерка и Matplotlib - PullRequest
       51

Кривая примерка и Matplotlib

0 голосов
/ 20 сентября 2019

У меня есть эти три переменные, и я хочу построить связь между двумя из них двумя переменными:

x = [0.125735  , 0.11753342, 0.11572967, 0.11963533, 0.1255283 ,
       0.13183589, 0.13904629, 0.14754317, 0.15548172, 0.16429631,
       0.17474308, 0.18641375]
y = [0.11917991, 0.10663986, 0.09897077, 0.09291739, 0.08743263,
       0.08346636, 0.08161819, 0.08132199, 0.08216186, 0.0834759 ,
       0.08551088, 0.08770163]
z = [1, 2, 3, 4, 5,
       6, 7, 8, 9, 10 ,
       11, 12]

enter image description here

на рисунке показаноx,y.Я хочу уместить линию, которая проходит через все эти точки, и обозначить каждую точку z.

Ответы [ 2 ]

3 голосов
/ 20 сентября 2019

Без центрирования

Вот краткий пример подгонки точек в полярных координатах:

x = [0.125735  , 0.11753342, 0.11572967, 0.11963533, 0.1255283 ,
     0.13183589, 0.13904629, 0.14754317, 0.15548172, 0.16429631,
     0.17474308, 0.18641375]
y = [0.11917991, 0.10663986, 0.09897077, 0.09291739, 0.08743263,
     0.08346636, 0.08161819, 0.08132199, 0.08216186, 0.0834759 ,
     0.08551088, 0.08770163]
z = [1, 2, 3, 4, 5,
     6, 7, 8, 9, 10 ,
     11, 12]

# you need numpy
import numpy as np
import matplotlib.pyplot as plt

x = np.array(x)
y = np.array(y)

r = np.sqrt(x*x + y*y)
theta = np.arctan2(x, y)

plt.scatter(theta, r, z, z)
plt.colorbar()
plt.grid()
plt.title('polar coords')
plt.xlabel('$\\theta$ [rad]')
plt.ylabel('r')

p = np.polyfit(theta, r, 2)
xfit = np.linspace(0.8, 1.15, 15)
yfit = np.polyval(p, x)

plt.plot(xfit, yfit, '--')
plt.legend(['original data', 'fit'])

polar coordinate fit

С центрированием

Мы могли бы добиться большего успеха, если бы мы сначала центрировали точки:

# find the averages to find the centroid of the data
x_avg = x.mean()
y_avg = y.mean()

# center the data
x_star = x - x_avg
y_star = y - y_avg

# now find the radii
r = np.sqrt(x_star*x_star + y_star*y_star)

# make sure points are between 0 adn 360[degrees]
theta = np.degrees(np.arctan2(y_star, x_star)) % 360

plt.scatter(theta, r, z, z)
plt.colorbar()
plt.grid()
plt.title('polar coords')
plt.ylabel('r')
plt.xlabel('$\\theta$ [degrees]')

# fit with 3rd order polynomial
# because there are 2 inflection points
p = np.polyfit(theta, r, 3)

# plot fit
x_fit = np.linspace(90, 360, 270)
y_fit = np.polyval(p, x_fit)
plt.plot(x_fit, y_fit, '--')
plt.legend(['original data', 'fit'])

centered and rotated

Финальная строка соответствия

Вот итоговая строка соответствия исходных данных:

x_out = y_fit * np.cos(np.radians(x_fit)) + x_avg
y_out = y_fit * np.sin(np.radians(x_fit)) + y_avg

plt.scatter(x, y, z, z)
plt.plot(x_out, y_out, '--')
plt.colorbar()
plt.grid()
plt.title('output fit line')
plt.legend(['original data', 'fit'])

enter image description here

0 голосов
/ 21 сентября 2019

Здесь представлен графический 3D-монтажник поверхностей с трехмерной диаграммой рассеяния, трехмерной диаграммой поверхности и контурной диаграммой.График контура показывает, что поверхность четко изогнута, поэтому уравнение этого примера подходит лучше, чем плоскость плоской поверхности.Вы должны быть в состоянии щелкнуть и перетащить 3D-графики и повернуть их в 3-х местах для визуального осмотра.Используя ваши данные и простое уравнение степени "z = a * pow (x, b) + c * pow (y, d)" с подобранными параметрами a = 2.14091547e + 02, b = 1.56841786e + 00, c = -2.24366942e + 03 и d = 2,69437535e + 00 дают RMSE = 0,1122 и R-sqiared = 0,9989

scatter

surface

contour

import numpy, scipy, scipy.optimize
import matplotlib
from mpl_toolkits.mplot3d import  Axes3D
from matplotlib import cm # to colormap 3D surfaces from blue to red
import matplotlib.pyplot as plt

graphWidth = 800 # units are pixels
graphHeight = 600 # units are pixels

# 3D contour plot lines
numberOfContourLines = 16


xData = numpy.array([0.125735  , 0.11753342, 0.11572967, 0.11963533, 0.1255283 , 0.13183589, 0.13904629, 0.14754317, 0.15548172, 0.16429631, 0.17474308, 0.18641375], dtype=float)
yData = numpy.array([0.11917991, 0.10663986, 0.09897077, 0.09291739, 0.08743263, 0.08346636, 0.08161819, 0.08132199, 0.08216186, 0.0834759 , 0.08551088, 0.08770163], dtype=float)
zData = numpy.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10 , 11, 12], dtype=float)


def func(data, a, b, c, d):
    x = data[0]
    y = data[1]
    return a * numpy.power(x, b) + c * numpy.power(y, d)


def SurfacePlot(func, data, fittedParameters):
    f = plt.figure(figsize=(graphWidth/100.0, graphHeight/100.0), dpi=100)

    matplotlib.pyplot.grid(True)
    axes = Axes3D(f)

    x_data = data[0]
    y_data = data[1]
    z_data = data[2]

    xModel = numpy.linspace(min(x_data), max(x_data), 20)
    yModel = numpy.linspace(min(y_data), max(y_data), 20)
    X, Y = numpy.meshgrid(xModel, yModel)

    Z = func(numpy.array([X, Y]), *fittedParameters)

    axes.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm, linewidth=1, antialiased=True)

    axes.scatter(x_data, y_data, z_data) # show data along with plotted surface

    axes.set_title('Surface Plot (click-drag with mouse)') # add a title for surface plot
    axes.set_xlabel('X Data') # X axis data label
    axes.set_ylabel('Y Data') # Y axis data label
    axes.set_zlabel('Z Data') # Z axis data label

    plt.show()
    plt.close('all') # clean up after using pyplot or else there can be memory and process problems


def ContourPlot(func, data, fittedParameters):
    f = plt.figure(figsize=(graphWidth/100.0, graphHeight/100.0), dpi=100)
    axes = f.add_subplot(111)

    x_data = data[0]
    y_data = data[1]
    z_data = data[2]

    xModel = numpy.linspace(min(x_data), max(x_data), 20)
    yModel = numpy.linspace(min(y_data), max(y_data), 20)
    X, Y = numpy.meshgrid(xModel, yModel)

    Z = func(numpy.array([X, Y]), *fittedParameters)

    axes.plot(x_data, y_data, 'o')

    axes.set_title('Contour Plot') # add a title for contour plot
    axes.set_xlabel('X Data') # X axis data label
    axes.set_ylabel('Y Data') # Y axis data label

    CS = matplotlib.pyplot.contour(X, Y, Z, numberOfContourLines, colors='k')
    matplotlib.pyplot.clabel(CS, inline=1, fontsize=10) # labels for contours

    plt.show()
    plt.close('all') # clean up after using pyplot or else there can be memory and process problems


def ScatterPlot(data):
    f = plt.figure(figsize=(graphWidth/100.0, graphHeight/100.0), dpi=100)

    matplotlib.pyplot.grid(True)
    axes = Axes3D(f)
    x_data = data[0]
    y_data = data[1]
    z_data = data[2]

    axes.scatter(x_data, y_data, z_data)

    axes.set_title('Scatter Plot (click-drag with mouse)')
    axes.set_xlabel('X Data')
    axes.set_ylabel('Y Data')
    axes.set_zlabel('Z Data')

    plt.show()
    plt.close('all') # clean up after using pyplot or else there can be memory and process problems


if __name__ == "__main__":

    data = [xData, yData, zData]

    initialParameters = [100.0, 1.0, 1000.0, 1.0]

    # here a non-linear surface fit is made with scipy's curve_fit()
    fittedParameters, pcov = scipy.optimize.curve_fit(func, [xData, yData], zData, p0 = initialParameters)

    ScatterPlot(data)
    SurfacePlot(func, data, fittedParameters)
    ContourPlot(func, data, fittedParameters)

    print('fitted prameters', fittedParameters)

    modelPredictions = func(data, *fittedParameters) 

    absError = modelPredictions - zData

    SE = numpy.square(absError) # squared errors
    MSE = numpy.mean(SE) # mean squared errors
    RMSE = numpy.sqrt(MSE) # Root Mean Squared Error, RMSE
    Rsquared = 1.0 - (numpy.var(absError) / numpy.var(zData))
    print('RMSE:', RMSE)
    print('R-squared:', Rsquared)
...