Matplotlib - Как построить линии минимального и максимального градиента через столбцы ошибок? - PullRequest
0 голосов
/ 28 октября 2018

Мой код:

import matplotlib
import numpy as np
import matplotlib.pyplot as plt
from lmfit import Model

def bestfit(x, m, c):
    return m * x + c

x = [2.8672E-02, 2.2199E-02, 1.8180E-02, 1.5410E-02, 1.3325E-02]
y = [8.64622E-03, 7.07473E-03, 6.13109E-03, 5.46607E-03, 4.90341E-03]
xerror =[8.2209E-07, 4.9280E-07, 3.3052E-07, 2.3748E-07, 1.7756E-07]
yerror = [1.62083E-04, 1.45726E-04, 1.38127E-04, 1.26587E-04, 1.22042E-04]

mod = Model(bestfit)
params = mod.make_params(m = 0.2421, c = 0.0017)
result = mod.fit(y, params, x = x)
print(result.fit_report())
print(1 - result.residual.var() / np.var(y))

matplotlib.rcParams['font.serif'] = "Times New Roman"
matplotlib.rcParams['font.family'] = "serif"
plt.plot(x, y, 'bo', markersize = 1.5)
plt.plot(x, result.best_fit, color = 'red', linewidth = 0.5)
plt.xlabel(r'Inverse Mass $g^{-1}$')
plt.ylabel('Damping Coefficient $s^{-1}$')


plt.errorbar(x, y, xerror, yerror)
plt.show()

Я надеюсь создать линии минимального и максимального градиента вместе с их уравнениями, например, так:

enter image description here

Мне удалось сделать это в Excel, но для этого потребовался ручной ввод 4 крайних точек данных.

Как мне сделать это автоматически?

1 Ответ

0 голосов
/ 28 октября 2018

Мне не ясно, какие кривые показывает другая программа.Это выглядит так, как будто вы просто рисуете линию через точки

  (x[0], y[0]-yerror[0]), (x[-1], y[-1]+yerror[-1])
  (x[0], y[0]+yerror[0]), (x[-1], y[-1]-yerror[-1])

Это должно быть легко для вас с помощью matplotlib.Но это не кажется мне особенно значимым.

С другой стороны, если вы хотите включить в свой график некоторую меру неопределенности в результате подбора, тогда есть несколько вариантов.Во-первых, вы можете оценить модель, используя значения параметров, которые взяты из значений best_fit, и неопределенности в этих значениях.Например, вы можете сделать (когда у вас есть result):

pars = result.params

curve1 = bestfit(x, pars['m'].value+pars['m'].stderr, pars['c'].value)
curve2 = bestfit(x, pars['m'].value-pars['m'].stderr, pars['c'].value)
curve3 = bestfit(x, pars['m'].value, pars['c'].value+pars['c'].stderr)
curve4 = bestfit(x, pars['m'].value, pars['c'].value-pars['c'].stderr)
curve5 = bestfit(x, pars['m'].value+pars['m'].stderr, pars['c'].value+pars['c'].stderr)
curve6 = bestfit(x, pars['m'].value+pars['m'].stderr, pars['c'].value-pars['c'].stderr)
curve7 = bestfit(x, pars['m'].value-pars['m'].stderr, pars['c'].value+pars['c'].stderr)
curve8 = bestfit(x, pars['m'].value-pars['m'].stderr, pars['c'].value-pars['c'].stderr)

, а затем построить некоторые из них.

Более простым и, возможно, более информативным сюжетом будет использование метода eval_uncertainties из ModelResult.См. https://lmfit.github.io/lmfit-py/model.html#calculating-uncertainties-in-the-model-function Простое использование:

dely = result.eval_uncertainty()
plt.fill_between(x, result.best_fit-dely, result.best_fit+dely, color="#ABABAB")

Кроме того, поскольку у вас есть неопределенности в y, вы можете использовать их в самом подгонке.Чтобы сделать это с lmfit.Model, вы должны передать 1.0/yerror как weight методу fit:

result = mod.fit(y, params, x=x, weights=1.0/np.array(yerror))

(примечание: данные и неопределенности должны быть массивами, а несписки).Я думаю, что для ваших данных (где неопределенности схожи по размеру) это не будет иметь большого значения для наилучших значений и неопределенностей, но будет иметь значение в статистике, такой как хи-квадрат.

Наконец, для простой линейной модели (то есть модели, которая является линейной по параметрам, как эта), вам не нужно использовать итеративный подход, такой как lmfit.Model, но вы могли бы использоватьметоды линейной регрессии.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...