奇怪的 matplotlib 直方图:x 限制的变化破坏了直方图

Posted

技术标签:

【中文标题】奇怪的 matplotlib 直方图:x 限制的变化破坏了直方图【英文标题】:Weird matplotlib histogram: a change in x limit spoils histogram 【发布时间】:2021-12-23 03:50:08 【问题描述】:

我正在做一个与 $\chi^2$ 分布相关的直方图。

我要表示的值是一个概率,在这种情况下,几乎所有的概率都是1。这是我在不修改x限制的情况下得到的直方图:

值计算正确,直方图具有应有的形式。问题是x轴。由于概率在 0 和 1 之间,刻度很难阅读,限制没有意义。所以我添加了 ax1.set_xlim([0, 1]) 行,结果是:

垃圾箱在哪里?为什么这不起作用?我试图改变垃圾箱的数量,限制......

这里是完整的代码:

import numpy as np
import numpy.random as rnd
import matplotlib.pyplot as plt
from scipy.special import gamma as gamma
import scipy.integrate as inte


rnd.seed(1)


def chi2(mu, sig, x):
    if sig  != 0:
        return np.sum(((x-mu)/sig)**2)


def chi2PDF(n):
    cte = 2**(n/2)*gamma(n/2)
    noCTE = lambda x : x**(n/2-1)*np.exp(-x/2)
    pdf = lambda chi2 : noCTE(chi2)/cte
    return pdf


# returns the normal distribution of the experiment
def experiment(mean, sig, n):
    return rnd.normal(mean, sig, n)


mTeo = 130
mTeoNew = 145
sigTeo = 10

n = 10 # measurements in one experiment
N = int(1e4) # number of experiments

bins = 100 # number of bins in plots

# calculate chi2 from experiments
chi2Exp = np.array([chi2(mTeo, mTeoNew, experiment(mTeo, sigTeo, n)) for i in range(N)])
# determine 0 and max values of chi2 obtained
rangeChi2 = np.linspace(0, np.max(chi2Exp), bins)
# theorecial chi2 PDF
chi2PDFTeo = chi2PDF(n)
# values of the theoretical chi2 PDF
chi2Teo = chi2PDFTeo(rangeChi2)

def p_x_bigger_x0(n, x0):
    return inte.quad(chi2PDF(n), x0, np.inf)[0]


probs = []
for i in range(len(chi2Exp)):
    probs.append(p_x_bigger_x0(n, chi2Exp[i]))
probs = np.array(probs)

#plot

fig = plt.figure()

ax1 = plt.subplot2grid(shape = (1, 1),
                       loc = (0, 0),
                       rowspan = 1,
                       colspan = 1,
                       fig = fig)

hist = ax1.hist(probs,
                bins = bins)

ax1.set_xlabel('$P(\chi^2\geq\chi^2_0)$')
ax1.set_ylabel('Cuentas')

#ax1.set_xlim([0, 1]) # problem here

plt.show()

【问题讨论】:

如果您检查直方图跨度 (~ 2e-8),问题是您的 bin 太小了,它们甚至在[0,1].. 范围内都没有 1 个像素宽度。当您的值跨度非常小时,显示不在 0,1 范围内的值的方法 @UlisesBussi 我不确定这是否是问题所在。如果我在范围为[0,1] 时设置bins=1,则应显示包含所有数据的单箱直方图,但它是(或看起来)空的。 即使有一个 bin,这个 bim 的“大”也是 4e-8.... 问题是我确定.. 试试看:做 1 个 bin 直方图,将范围设置为 [0,1] (你什么也看不到),然后把它改成[0.9,1.1](还是什么都没有)。最后放[0.99999,1.00001],在那里你会看到一条小线(如果没有分别添加9和0,直到你看到栏) 【参考方案1】:

您可以将symlog 用于您的情节。

代码

plt.rcParams['figure.figsize'] = [10,5]
fig = plt.figure()
ax1 = plt.subplot2grid(shape = (1, 1),
                       loc = (0, 0),
                       rowspan = 1,
                       colspan = 1,
                       fig = fig)

hist = ax1.hist(probs, bins = bins)

ax1.set_xlabel('$P(\chi^2\geq\chi^2_0)$')
ax1.set_ylabel('Cuentas')
plt.yscale("symlog")
plt.show()

结果

【讨论】:

这个想法是为了搭上 1e-8+1。最后,数据也有问题,所以这不是正确的数据;用对了就没有这个问题了。

以上是关于奇怪的 matplotlib 直方图:x 限制的变化破坏了直方图的主要内容,如果未能解决你的问题,请参考以下文章

如何在 matplotlib 中根据 x 轴更改直方图颜色

如何在一个包含多个 matplotlib 直方图的图中设置 x 轴的边界并只创建一列图?

05-matplotlib-直方图

matplotlib可视化篇hist()--直方图

在Python matplotlib中更改X轴步骤[重复]

如何用matplotlib ArtistAnimation绘制直方图或条形动画?