Python - Matplotlib: 绘制概率密度函数时归一化轴

7 投票
1 回答
33562 浏览
提问于 2025-04-18 14:29

我正在使用Python和一些扩展库来获取和绘制概率密度函数。虽然我能成功绘制出来,但在调整坐标轴方面遇到了一些问题。

import decimal
import numpy as np
import scipy.stats as stats
import pylab as pl
import matplotlib.pyplot as plt
from decimal import *
from scipy.stats import norm

lines=[]

fig, ax = plt.subplots(1, 1)
mean, var, skew, kurt = norm.stats(moments='mvsk')

#Here I delete some lines aimed to fill the list with values

Long = len(lines)
Maxim = max(lines) #MaxValue
Minim = min(lines) #MinValue
av = np.mean(lines) #Average
StDev = np.std(lines) #Standard Dev.

x = np.linspace(Minim, Maxim, Long)
ax.plot(x, norm.pdf(x, av, StDev),'r-', lw=3, alpha=0.9, label='norm pdf')

weights = np.ones_like(lines)/len(lines)

ax.hist(lines, weights = weights, normed=True, histtype='stepfilled', alpha=0.2)
ax.legend(loc='best', frameon=False)
plt.show()

结果是 得到的图

我希望能这样表达: - x轴以0为中心,并与标准差相关联 - y轴与直方图和百分比(归一化为1)相关联
对于x轴,像下面这张图片 期望的图

而y轴希望像最后这张图片 期望的y轴

我已经通过单独绘制直方图并使用指令 weights = weights 来调整y轴,但在这里我无法做到。我把它放进代码里,但实际上在这种情况下没有任何作用。

任何帮助都将不胜感激

1 个回答

3

y轴的标准化方式是让曲线下的面积等于1。如果你已经用 normed=True 进行了标准化,那么给每个数据点加上相同的权重就没有意义了。

首先,你需要把数据调整到0:

 lines -= mean(lines)

然后再绘制图形。

下面这个应该是一个有效的最小示例:

import numpy as np                                                               
from numpy.random import normal                                                  
import matplotlib.pyplot as plt
from scipy.stats import norm                                                  

# gaussian distributed random numbers with mu =4 and sigma=2                     
x = normal(4, 2, 10000)                                                            

mean = np.mean(x)
sigma = np.std(x)

x -= mean 

x_plot = np.linspace(min(x), max(x), 1000)                                                               

fig = plt.figure()                                                               
ax = fig.add_subplot(1,1,1)                                                      

ax.hist(x, bins=50, normed=True, label="data")
ax.plot(x_plot, norm.pdf(x_plot, mean, sigma), 'r-', label="pdf")                                                          

ax.legend(loc='best')

x_ticks = np.arange(-4*sigma, 4.1*sigma, sigma)                                  
x_labels = [r"${} \sigma$".format(i) for i in range(-4,5)]                       

ax.set_xticks(x_ticks)                                                           
ax.set_xticklabels(x_labels)                                                     

plt.show() 

输出的图像是这个: plot outout

另外,你的导入太多了。你导入了 decimals 两次,甚至有一次是用 * 导入的。还有,numpy、pyplot 和 scipy 都已经包含在 pylab 里了。为什么还要导入整个 scipy.stats,然后再单独导入其中的 norm 呢?

撰写回答