如何在直方图中居中标签
我有一个名为 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()
的解决方案。我们把它分成两个部分来讲:
- 让x轴标记为
0 1 2 3
。 - 让每个柱子的标签在中间。
要让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()
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()