如何在直方图中居中标签

38 投票
7 回答
74248 浏览
提问于 2025-04-18 03:55

我有一个名为 results 的numpy数组,它的样子是这样的:

[ 0.  2.  0.  0.  0.  0.  3.  0.  0.  0.  0.  0.  0.  0.  0.  2.  0.  0.
  0.  0.  0.  1.  0.  0.  0.  0.  0.  0.  0.  1.  0.  0.  0.  0.  0.  0.
  0.  1.  1.  0.  0.  0.  0.  2.  0.  3.  1.  0.  0.  2.  2.  0.  0.  0.
  0.  0.  0.  0.  0.  1.  1.  0.  0.  0.  0.  0.  0.  2.  0.  0.  0.  0.
  0.  1.  0.  0.  0.  0.  0.  0.  0.  0.  0.  3.  1.  0.  0.  0.  0.  0.
  0.  0.  0.  1.  0.  0.  0.  1.  2.  2.]

我想给它画一个直方图。我试过这样做:

import matplotlib.pyplot as plt
plt.hist(results, bins=range(5))
plt.show()

这样做后,我得到了一个直方图,x轴的标签是 0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0

我希望x轴的标签改成 0 1 2 3,并且这些标签要放在每个柱子的中间。该怎么做呢?

7 个回答

0

正如Jarad在他的回答中提到的,条形图是一种很不错的方式来展示数据。下面是使用pandas库绘制条形图的简单方法。

import pandas as pd
import matplotlib.pyplot as plt

arr = [ 0.,  2.,  0.,  0.,  0.,  0.,  3.,  0.,  0.,  0.,  0.,  0.,  0.,
        0.,  0.,  2.,  0.,  0.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,
        0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  1.,
        0.,  0.,  0.,  0.,  2.,  0.,  3.,  1.,  0.,  0.,  2.,  2.,  0.,
        0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  1.,  0.,  0.,  0.,  0.,
        0.,  0.,  2.,  0.,  0.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,
        0.,  0.,  0.,  0.,  0.,  3.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,
        0.,  0.,  1.,  0.,  0.,  0.,  1.,  2.,  2.]

col = 'name'
pd.DataFrame({col : arr}).groupby(col).size().plot.bar()
plt.show()
11

你可以用 np.histogram 来制作一个 bar 图。

看看这个例子:

his = np.histogram(a,bins=range(5))
fig, ax = plt.subplots()
offset = .4
plt.bar(his[1][1:],his[0])
ax.set_xticks(his[1][1:] + offset)
ax.set_xticklabels( ('1', '2', '3', '4') )

在这里输入图片描述

编辑:为了让柱子彼此紧挨着,需要调整宽度参数。

 fig, ax = plt.subplots()
 offset = .5
 plt.bar(his[1][1:],his[0],width=1)
 ax.set_xticks(his[1][1:] + offset)
 ax.set_xticklabels( ('1', '2', '3', '4') )

在这里输入图片描述

19

这里有一个只用到 plt.hist() 的解决方案。我们把它分成两个部分来讲:

  1. 让x轴标记为 0 1 2 3
  2. 让每个柱子的标签在中间。

要让x轴标记为 0 1 2 3,而不出现 .5 的值,你可以使用 plt.xticks() 这个函数,并把你想要的值作为参数传进去。在你的情况下,因为你想要的是 0 1 2 3,你可以调用 plt.xticks(range(4))

要让标签在每个柱子的中间,你可以在 plt.hist() 函数中传入参数 align='left'。下面是你的代码,做了最小的修改来实现这个效果。

import matplotlib.pyplot as plt

results = [0,  2,  0,  0,  0,  0,  3,  0,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,
           0,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,
           0,  1,  1,  0,  0,  0,  0,  2,  0,  3,  1,  0,  0,  2,  2,  0,  0,  0,
           0,  0,  0,  0,  0,  1,  1,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,
           0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  3,  1,  0,  0,  0,  0,  0,
           0,  0,  0,  1,  0,  0,  0,  1,  2,  2]

plt.hist(results, bins=range(5), align='left')
plt.xticks(range(4))
plt.show()

enter image description here

23

下面这个替代方案可以和 plt.hist() 一起使用,这样的好处是你可以在调用 pandas.DataFrame.hist() 之后再使用它。

import numpy as np

def bins_labels(bins, **kwargs):
    bin_w = (max(bins) - min(bins)) / (len(bins) - 1)
    plt.xticks(np.arange(min(bins)+bin_w/2, max(bins), bin_w), bins, **kwargs)
    plt.xlim(bins[0], bins[-1])

(最后一行虽然不是提问者严格要求的,但这样输出看起来会更好)

你可以这样使用:

import matplotlib.pyplot as plt
bins = range(5)
plt.hist(results, bins=bins)
bins_labels(bins, fontsize=20)
plt.show()

结果:成功!

64

其他的回答对我来说都不太合适。使用 plt.bar 而不是 plt.hist 的好处在于,柱状图可以使用 align='center' 来对齐:

import numpy as np
import matplotlib.pyplot as plt

arr = np.array([ 0.,  2.,  0.,  0.,  0.,  0.,  3.,  0.,  0.,  0.,  0.,  0.,  0.,
        0.,  0.,  2.,  0.,  0.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,
        0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  1.,
        0.,  0.,  0.,  0.,  2.,  0.,  3.,  1.,  0.,  0.,  2.,  2.,  0.,
        0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  1.,  0.,  0.,  0.,  0.,
        0.,  0.,  2.,  0.,  0.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,
        0.,  0.,  0.,  0.,  0.,  3.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,
        0.,  0.,  1.,  0.,  0.,  0.,  1.,  2.,  2.])

labels, counts = np.unique(arr, return_counts=True)
plt.bar(labels, counts, align='center')
plt.gca().set_xticks(labels)
plt.show()

在直方图中居中标签

撰写回答