42

我想使用 Matplotlib 在预先计算的数据上绘制直方图。例如,假设我有原始数据

data = [1, 2, 2, 3, 4, 5, 5, 5, 5, 6, 10]

鉴于这些数据,我可以使用

pylab.hist(data, bins=[...])

绘制直方图。

就我而言,数据已预先计算并表示为字典:

counted_data = {1: 1, 2: 2, 3: 1, 4: 1, 5: 4, 6: 1, 10: 1}

理想情况下,我想将这个预先计算的数据传递给一个直方图函数,让我可以控制 bin 宽度、绘图范围等,就好像我传递了原始数据一样。作为一种解决方法,我将我的计数扩展到原始数据:

data = list(chain.from_iterable(repeat(value, count)
            for (value, count) in counted_data.iteritems()))

counted_data当包含数百万个数据点的计数时,这是低效的。

有没有更简单的方法可以使用 Matplotlib 从我预先计算的数据中生成直方图?

或者,如果只对已预先分箱的条形图数据进行最简单的处理,是否有一种方便的方法可以将我的每项计数“汇总”到分箱计数中?

4

5 回答 5

32

您可以使用weights关键字参数np.histgramplt.hist在下面调用)

val, weight = zip(*[(k, v) for k,v in counted_data.items()])
plt.hist(val, weights=weight)

假设你只有整数作为键,你也可以bar直接使用:

min_bin = np.min(counted_data.keys())
max_bin = np.max(counted_data.keys())

bins = np.arange(min_bin, max_bin + 1)
vals = np.zeros(max_bin - min_bin + 1)

for k,v in counted_data.items():
    vals[k - min_bin] = v

plt.bar(bins, vals, ...)

其中 ... 是您想要传递给bar (doc)的任何参数

如果您想重新分类您的数据,请参阅直方图,其中包含表示频率的单独列表

于 2013-10-06T18:58:34.220 回答
21

我使用pyplot.histweights选项按每个键的值加权,生成我想要的直方图:

pylab.hist(counted_data.keys(), weights=counted_data.values(), bins=range(50))

这使我可以依靠hist重新分类我的数据。

于 2013-10-06T22:26:09.863 回答
5

您还可以使用 seaborn 绘制直方图:

import seaborn as sns

sns.distplot(
    list(
        counted_data.keys()
    ), 
    hist_kws={
        "weights": list(counted_data.values())
    }
)
于 2018-04-16T12:20:56.220 回答
3

“bins”数组的长度应该比“counts”的长度长。这是完全重建直方图的方法:

import numpy as np
import matplotlib.pyplot as plt
bins = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9]).astype(float)
counts = np.array([5, 3, 4, 5, 6, 1, 3, 7]).astype(float)
centroids = (bins[1:] + bins[:-1]) / 2
counts_, bins_, _ = plt.hist(centroids, bins=len(counts),
                             weights=counts, range=(min(bins), max(bins)))
plt.show()
assert np.allclose(bins_, bins)
assert np.allclose(counts_, counts)
于 2017-11-07T06:42:47.797 回答
0

添加到 tacaswell 的评论中,对于大量垃圾箱 (>1e4) 而言,plt.bar它可能比这里更有效。plt.hist特别是对于一个拥挤的随机图,您只需要绘制最高的条,因为看到它们所需的宽度无论如何都会覆盖它们的大部分邻居。您可以挑选出最高的条形图并绘制它们

i, = np.where(vals > min_height)
plt.bar(i,vals[i],width=len(bins)//50)

其他统计趋势可能更喜欢每隔 100 个柱或类似的东西绘制一次。

这里的技巧是plt.hist想要绘制所有的垃圾箱,而plt.bar让你只绘制更稀疏的可见垃圾箱集。

于 2021-05-08T01:48:01.557 回答