在matplotlib中,ax.plot函数是用来画曲线的,而ax.hist函数则用来画直方图(histogram)。
下面我们用python代码换一个直方图,10000个符合正态分布的随机数,将他们按照直方图画出来:
import numpy as np
import matplotlib.pyplot as plt
x = np.random.randn(10000)
fig = plt.figure()
ax = fig.add_subplot()
ax.hist(x, bins=50, color='blue', alpha=0.7)
plt.show()
注意ax.hist函数,数据的输入只有x,x可以是一个sequence,也可以是matrix;
bins控制直方图中等宽分组的数量,默认为10,不过应该很少用默认值吧;
alpha控制直方图颜色的透明度。(plot等其它函数中,也有这个参数)
这个直方图怎么看,y轴表示数据出现的频率或次数,x轴是按bins参数输入进行分组。直方图,可以理解为由一系列高度不等的纵向条柱来表示数据分布特征的统计报告图,它是对原始数据进行压缩的结果。
直方图分组的区间
我没有找到特别权威的说明,不过,通过阅读matplotlib官方教材能够发现,bins的值如果是一个整数,x轴的区间就进行等宽划分;bins只也可以是一个sequence对象,用来进行不等宽划分x轴。
不管怎么分x轴的区间,每一个分组,都是左封闭右开放,只有最后一个分组,是左右都封闭的!(想一想这样是合理的,左边不封闭,最左边的那个分组就没法处理了)
>>> plt.hist((1,2,3,4,5,6,7,8,2), bins=(1,2,3,4,5,6,8))
(array([1., 2., 1., 1., 1., 3.]), array([1, 2, 3, 4, 5, 6, 8]),
ject of 6 artists>)
对(1,2,3,4,5,6,7,8,2)话直方图,但是bins=(1,2,3,4,5,6,8),即6-8为一个大分组,有3个数字落在这个区间,数据中出现了两次2,第1个分组是[1,2),不包含2,2因此包含在第2个分组中[2,3)。这样画出来的直方图如下:
上面这个图其实看着不是很好看,全都粘在一起了,我们可以通过rwidth参数(float,分组区间大小的百分比)来控制各个bar之间的间隔,注意此时图像上的位置,已经不再是真实的分组区间,x轴的刻度也可以用xticks函数来精确控制:
>>> plt.hist((1,2,3,4,5,6,7,8,2), bins=(1,2,3,4,5,6,8), rwidth=0.9, color='purpl
e', alpha=0.5)
(array([1., 2., 1., 1., 1., 3.]), array([1, 2, 3, 4, 5, 6, 8]),
ject of 6 artists>)
>>> plt.xticks(range(1,10,1))
效果如下:
当bins参数为一个sequence时,实际上就是给dataset指定了一个range,即bins所括起来的区间不需要与dataset的区间一致。当bins是一个int时,我们可以用range参数来指定有效区间,将不在区间范围内的outliers排除在直方图的统计中。
输入数据为matrix时的直方图
输入数据x如果是一个matrix,matplotlib会把它的每一个列向量当做一个dataset来画直方图,然后将多个直方图并排在一起放在一个图中。此时,分组在x轴上的分割就不是精确的了(就像使用了rwidth参数):
>>> plt.hist(((1,2,3,4,5,1,2,3,4,5,1,1,2,2,3,4,5,5),(1,2,3,4,5),(1,2,3,3,3)), bi
ns=4)
(array([[4., 4., 3., 7.],
[1., 1., 1., 2.],
[1., 1., 3., 0.]]), array([1., 2., 3., 4., 5.]),
r objects>)
从返回值可以看出,分组为array([1., 2., 3., 4., 5.]),但为了作图,多个柱形公用一个区间,他们只能在这个区间内进行某种排列,两边还要留点空余出来:
根据需要,我们可以此时将多个直方图的bar堆叠起来(stack),使用stacked=True参数,配合rwidth,代码和效果如下:
>>> plt.hist(((1,2,3,4,5,1,2,3,4,5,1,1,2,2,3,4,5,5),(1,2,3,4,5),(1,2,3,3,3)), bi
ns=4, stacked=True, rwidth=0.9)
(array([[4., 4., 3., 7.],
[5., 5., 4., 9.],
[6., 6., 7., 9.]]), array([1., 2., 3., 4., 5.]),