[英]How to fit a normal distribution for scatter plot data
我有一個 dataframe ,其 x (第 x 列)和 y (第 1 列)值低於我得到mean
和stdev
。
接下來我將它們一起繪制在一張圖表上,但它看起來非常錯誤,不僅僅是擬合曲線移動了,我不確定它有什么問題。
import matplotlib.pyplot as plt
from scipy import stats
from scipy import optimize
import numpy as np
data_sample = {'x': [0,1,2,3,4,5,6,7,8,9,10], '1': [0,1,2,3,4,5,4,3,2,1,0]}
def test_func(x, a, b):
return stats.norm.pdf(x,a,b)
params, cov_params = optimize.curve_fit(test_func, data_sample['x'], data_sample['1'])
print(params)
plt.scatter(data_sample['x'], data_sample['1'], label='Data')
plt.plot(data_sample['x'] , test_func(data_sample['x'], params[0], params[1]), label='Fitted function')
plt.legend(loc='best')
plt.show()
需要對數據進行歸一化,使曲線下的面積為 1。要計算面積,當所有 x 值相差 1 時,您需要 y 值的總和。 如果 x 值之間的空間大於或小於 1,則還應包括該因子。 另一種計算面積的方法是np.trapz()
。
進行擬合時需要使用歸一化因子。 使用原始數據繪制曲線時需要發生相反的情況。
當您嘗試將高斯 pdf function 擬合到非歸一化點時,“最佳”擬合是一個非常窄、非常高的峰值。 這個峰值試圖接近中心的y=5
值。
下面的示例代碼將列表轉換為 numpy arrays,因此可以更輕松地編寫函數。 此外,為了繪制平滑曲線,使用更詳細的 x 值。
import matplotlib.pyplot as plt
from scipy import stats
from scipy import optimize
import numpy as np
def test_func(x, a, b):
return stats.norm.pdf(x, a, b)
data_sample = {'x': np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),
'1': np.array([0, 1, 2, 3, 4, 5, 4, 3, 2, 1, 0])}
# x_dist = (data_sample['x'].max() - data_sample['x'].min()) / (len(data_sample['x']) - 1)
# normalization_factor = sum(data_sample['1']) * x_dist
normalization_factor = np.trapz(data_sample['1'], data_sample['x']) # area under the curve
params, pcov = optimize.curve_fit(test_func, data_sample['x'], data_sample['1'] / normalization_factor)
plt.scatter(data_sample['x'], data_sample['1'], clip_on=False, label='Data')
x_detailed = np.linspace(data_sample['x'].min() - 3, data_sample['x'].max() + 3, 200)
plt.plot(x_detailed, test_func(x_detailed, params[0], params[1]) * normalization_factor,
color='crimson', label='Fitted function')
plt.legend(loc='best')
plt.margins(x=0)
plt.ylim(ymin=0)
plt.tight_layout()
plt.show()
PS:使用原始代碼(沒有歸一化),但使用更詳細的 x 值,窄曲線會更明顯:
x_detailed = np.linspace(min(data_sample['x']) - 1, max(data_sample['x']) + 1, 500)
plt.plot(x_detailed, test_func(x_detailed, params[0], params[1]), color='m', label='Fitted function')
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.