直方图 Matplotlib

Posted

技术标签:

【中文标题】直方图 Matplotlib【英文标题】:Histogram Matplotlib 【发布时间】:2011-07-16 18:14:03 【问题描述】:

所以我有一个小问题。我有一个 scipy 数据集,它已经是直方图格式,所以我有 bin 的中心和每个 bin 的事件数。我现在如何绘制为直方图。我试着做

bins, n=hist()

但它不喜欢那样。有什么建议吗?

【问题讨论】:

【参考方案1】:

从 matplotlib 3.4.0 开始

新的plt.stairs(或ax.stairs)直接与np.histogram一起工作:

np.histogram 返回计数和边 plt.stairs 接受计数和边

例如,给定 unutbu 的样本 x = 100 + 15 * np.random.randn(10000)

counts, edges = np.histogram(x, bins=50)
plt.stairs(counts, edges, fill=True)

或者,将np.histogram直接解压到plt.stairs

plt.stairs(*np.histogram(x, bins=50), fill=True)

有关how to use stair plots 的更多示例,请参阅官方 matplotlib 库。

【讨论】:

【参考方案2】:

我刚刚意识到 hist 文档明确说明了当您已经拥有 np.histogram 时该怎么做

counts, bins = np.histogram(data)
plt.hist(bins[:-1], bins, weights=counts)

这里的重要部分是您的计数只是权重。如果你这样做,你就不再需要 bar 功能了

【讨论】:

【参考方案3】:

这可能对某人有用。

Numpy 的直方图函数返回每个 bin 的边缘,而不是 bin 的值。这对于浮点数是有意义的,它可以位于一个区间内,但在处理离散值或整数(0、1、2 等)时可能不是所需的结果。特别是,从 np.histogram 返回的 bin 长度不等于计数/密度的长度。

为了解决这个问题,我使用 np.digitize 来量化输入,并计算每个 bin 的计数分数。您可以轻松编辑以获取整数计数。

def compute_PMF(data):
    import numpy as np
    from collections import Counter
    _, bins = np.histogram(data, bins='auto', range=(data.min(), data.max()), density=False)
    h = Counter(np.digitize(data,bins) - 1)
    weights = np.asarray(list(h.values())) 
    weights = weights / weights.sum()
    values = np.asarray(list(h.keys()))
    return weights, values
####

参考:

[1]https://docs.scipy.org/doc/numpy/reference/generated/numpy.histogram.html

[2] https://docs.scipy.org/doc/numpy/reference/generated/numpy.digitize.html

【讨论】:

【参考方案4】:

如果你愿意使用pandas

pandas.DataFrame('x':hist[1][1:],'y':hist[0]).plot(x='x',kind='bar')

【讨论】:

如果您要建议使用pandas,您可能应该包含一个指向他们网站的链接和一个更完整的示例来解释正在发生的事情。【参考方案5】:

我知道这并不能回答您的问题,但是当我搜索直方图的 matplotlib 解决方案时,我总是在这个页面上结束,因为简单的 histogram_demo 已从 matplotlib 示例库页面中删除。

这是一个不需要导入numpy 的解决方案。我只导入 numpy 来生成要绘制的数据x。它依赖于函数hist,而不是@unutbu 的answer 中的函数bar

import numpy as np
mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)

import matplotlib.pyplot as plt
plt.hist(x, bins=50)
plt.savefig('hist.png')

还可以查看matplotlib gallery 和matplotlib examples。

【讨论】:

"这里有一个解决方案,不需要 numpy" -- 第一行代码导入 numpy :) @Martin R. 这只是为了生成要绘制的数据。见第 4-6 行。不使用 numpy。【参考方案6】:

如果您不想要条形图,可以这样绘制:

import numpy as np
import matplotlib.pyplot as plt

mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)

bins, edges = np.histogram(x, 50, normed=1)
left,right = edges[:-1],edges[1:]
X = np.array([left,right]).T.flatten()
Y = np.array([bins,bins]).T.flatten()

plt.plot(X,Y)
plt.show()

【讨论】:

你也可以使用ax.step【参考方案7】:
import matplotlib.pyplot as plt
import numpy as np

mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)
hist, bins = np.histogram(x, bins=50)
width = 0.7 * (bins[1] - bins[0])
center = (bins[:-1] + bins[1:]) / 2
plt.bar(center, hist, align='center', width=width)
plt.show()

面向对象的接口也很简单:

fig, ax = plt.subplots()
ax.bar(center, hist, align='center', width=width)
fig.savefig("1.png")

如果您使用自定义(非常量)箱,您可以使用np.diff 计算宽度,将宽度传递给ax.bar 并使用ax.set_xticks 标记箱边缘:

import matplotlib.pyplot as plt
import numpy as np

mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)
bins = [0, 40, 60, 75, 90, 110, 125, 140, 160, 200]
hist, bins = np.histogram(x, bins=bins)
width = np.diff(bins)
center = (bins[:-1] + bins[1:]) / 2

fig, ax = plt.subplots(figsize=(8,3))
ax.bar(center, hist, align='center', width=width)
ax.set_xticks(bins)
fig.savefig("/tmp/out.png")

plt.show()

【讨论】:

有没有办法将 bin 边缘传递到条形图的 x 轴? @CMCDragonkai:plt.barwidth 参数可以接受类似数组的对象(而不是标量)。所以你可以使用width = np.diff(bins) 而不是width = 0.7 * (bins[1] - bins[0]) 但是 width 设置本身只设置栏的宽度对吗?我说的是 x 轴标签(即我想看到实际的 bin 边缘是 x 轴上的标签)。它应该类似于plt.hist 的工作方式。 @CMCDragonkai: 你可以使用ax.set_xticks 来设置xlabels。我在上面添加了一个示例来说明我的意思。

以上是关于直方图 Matplotlib的主要内容,如果未能解决你的问题,请参考以下文章

Python绘制图表matplotlib

常用的python库都有哪些

matplotlib

Matplotlib一.初识

L7-14 3D图形

R语言plotly可视化:可视化直方图归一化的直方图水平直方图互相重叠的直方图堆叠的直方图累积直方图通过bingroup参数设置多个直方图使用相同的bins设置自定义直方图条形的间距