【问题标题】:Python curve fitting on a barplot条形图上的 Python 曲线拟合
【发布时间】:2023-09-03 00:59:01
【问题描述】:

如何在条形图上拟合曲线?

我有一个方程,即扩散方程,它有一些未知参数,这些参数使曲线更大、更高等。另一方面,我有一个来自模拟的条形图。我想在条形图上拟合曲线,并找到曲线的最佳参数,我该怎么做?

这是我通过“手动拟合”获得的,所以基本上我手动更改了几个小时的所有参数。但是有没有办法用 python 做到这一点?

为简单起见,假设我有以下代码:

import matplotlib.pyplot as plt


list1 = []
for i in range(-5,6):
    list1.append(i)
    
width = 1/1.5

list2 = [0,0.2,0.6,3.5,8,10,8,3.5,0.6,0.2,0]

plt.bar(list1,list2,width)

plt.show()
T = 0.13
xx = np.arange(-6,6,0.01)
yy = 5*np.sqrt(np.pi)*np.exp(-((xx)**2)/(4*T))*scipy.special.erfc((xx)/(2*np.sqrt(T))) + np.exp(-((xx)**2)/(4*T)) 

plt.plot(xx,yy)

plt.show()

显然这里的拟合会非常困难,但无论如何,是否有任何函数或类似函数可以让我找到方程的最佳系数:(其中 T 已知)

y = A*np.sqrt(np.pi*D)*np.exp(-((x-E)**2)/(4*D*T))*scipy.special.erfc((x-E)/(2*np.sqrt(D*T))) + 300*np.exp(-((x-E)**2)/(4*D*T)) 

编辑:这与已经提出的问题和 scipy 文档示例不同。在后者中,“xdata”是相同的,而在我的情况下,它可能是也可能不是。此外,我还可以绘制此曲线拟合,文档中未显示。条的高度不是 x 的函数!所以我的 xdata 不是我的 ydata 的函数,这与文档中的不同。 要了解我的意思,请尝试稍微更改文档中的代码,以符合我的示例,请尝试以下操作:

def func(x,a,b,c):
    return a * np.exp(-b * x) + c
    
xdata = np.linspace(0,4,50)
y = func(xdata, 2.5, 1.3, 0.5)
ydata = [1,6,3,4,6,7,8,5,7,0,9,8,2,3,4,5]

popt, pcov = curve_fit(func,xdata,ydata)

如果你运行它,它就不起作用。原因是 ydata 有 16 个元素,函数有 50 个元素。发生这种情况是因为 y 从 xdata 中获取值,而 ydata 从另一组 x 值中获取值,这在此处是未知的。

谢谢

【问题讨论】:

  • curve fitting with python的可能重复
  • @lanery 不,不一样,我没有数据,我有一个条形图,它不会从同一个 x 范围内获取值!
  • @reptilicus,感谢您提供的链接,但是在我的示例中它不起作用,我的函数不会从条形图的同一 x 范围内获取 x 值
  • @lanery,而且我想找到参数,所以问题完全不同

标签: python-2.7 matplotlib curve-fitting best-fit-curve


【解决方案1】:

我坚持认为这个问题是重复的。以下是使用curve_fit 的典型工作流程的简要示例。如果您仍然认为您的情况有所不同,请告诉我。

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

# bar plot data
list1 = range(-5, 6)
list2 = [0, 0.2, 0.6, 3.5, 8, 10,
         8, 3.5, 0.6, 0.2, 0]
width = 1/1.5

plt.bar(list1, list2, width, alpha=0.75)

# fit bar plot data using curve_fit
def func(x, a, b, c):
    # a Gaussian distribution
    return a * np.exp(-(x-b)**2/(2*c**2))

popt, pcov = curve_fit(func, list1, list2)

x = np.linspace(-5, 5, 100)
y = func(x, *popt)

plt.plot(x + width/2, y, c='g')

【讨论】:

  • @Ianery,我不明白您为什么在y = func(x, *popt) 中使用*popt
  • @Euler_Salter 您可能从文档中知道,popt 是最适合数据的参数列表(abc)。所以我把func(x, *popt) 写成func(x, popt[0], popt[1], popt[2]) 的简写,其中popt[0]a 的最佳猜测,popt[1]b 的最佳猜测,popt[3] 是@987654338 的最佳猜测@.