import matplotlib.pyplot as plt
import numpy as np
入门
我们首先生成随机的数据:
x = np.arange(1, 7)
y = np.abs(np.random.randn(6))
直接调用 plt
的绘图方法:
plt.bar(x, y)
<BarContainer object of 6 artists>
当然,一个好的习惯是使用 Axes
对象:
fig = plt.figure()
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
ax.bar(x, y)
<BarContainer object of 6 artists>
ax.clear()
图像美化
设置颜色
我们可以使用 color
参数来改变条形图的颜色:
ax.bar(x, y, color='g')
fig
ax.clear()
甚至可以指定每个柱子都是不同颜色:
ax.bar(x, y, color=['r', 'g', 'b', 'y', 'c', 'm'])
fig
ax.clear()
设置轮廓
我们可以使用 edgecolor
参数来改变条形图的轮廓颜色:
ax.bar(x, y, edgecolor='k')
fig
ax.clear()
而 linewidth
参数可以调节边缘的粗细:
ax.bar(x, y, edgecolor='k', linewidth=3)
fig
ax.clear()
linestyle
参数与二维绘图 plot
同理,此处不再赘述。
设置填充
我们可以使用 hatch
参数来指定条形图的填充形状:
ax.bar(x, y, hatch='\\', edgecolor='k', color='w')
fig
ax.clear()
设置宽度
我们可以使用 width
参数来设置条形图的宽度:
ax.bar(x, y, width=0.5)
fig
width
参数的取值范围一般为 $(0, 1]$ 之间的浮点数。如果 width=1
,那么每个柱子之间就没有空隙。这个浮点数的几何意义相当于缩放比例。
ax.clear()
系列条形图
现在,我们需要统计 CSGO 七张服役地图 T 和 CT 的胜率,数据如下:
maps = ['Dust2', 'Inferno', 'Mirage', 'Nuke', 'Overpass', 'Train', 'Vertigo']
CT_win_rate = [53.7, 49.8, 48.1, 50.7, 57.9, 53.4, 58.6]
T_win_rate = [46.3, 50.2, 51.9, 49.3, 42.1, 46.6, 41.4]
我们需要设置好条形图的宽度。由于实例一共有两个系列(CT 和 T),我们可以将每个柱子的宽度设为 0.35,这样加起来一共 0.7,每一组柱子之间也有缝隙。
width = 0.35
下面设置条形图的绘制位置,它由 width
和标签的索引位置 x
决定:
x = np.arange(len(maps))
x_CT = x - width/2
x_T = x + width/2
绘制系列条形图:
y_CT = ax.bar(x_CT, CT_win_rate, color='blue', width=width, label='CT')
y_T = ax.bar(x_T, T_win_rate, color='orange', width=width, label='T')
fig
添加标签、标题和图例:
ax.set_xticks(x)
ax.set_ylim(40, 60)
ax.set_xticklabels(maps)
ax.set_ylabel('Win Rate (%)')
ax.legend(loc='upper right')
fig
为其添加水平网格线:
ax.grid(linestyle='-.', axis='y')
fig
网格线显示在了条形图上方,使用 zorder
参数改变各个元素的层数。
ax.clear()
y_CT = ax.bar(x_CT, CT_win_rate, color='blue', width=width, label='CT', zorder=2)
y_T = ax.bar(x_T, T_win_rate, color='orange', width=width, label='T', zorder=2)
ax.set_ylim(40, 60)
ax.set_xticks(x)
ax.set_xticklabels(maps)
ax.set_ylabel('Win Rate (%)')
ax.legend(loc='upper right')
ax.grid(linestyle='-.', axis='y', zorder=1)
fig
ax.clear()
水平条形图
x = np.arange(1, 7)
y = np.abs(np.random.randn(6))
Matplotlib 中使用 barh
来绘制水平条形图。
ax.barh(x, y)
fig
其余设置与普通的条形图几乎没有任何区别。
ax.clear()
堆叠条形图
我们现在给定一个 $3 \times 6$ 的矩阵,这三行数值都属于不同的系列,并且我们希望对其求和。
x = np.arange(1, 7)
y = np.abs(np.random.randn(3, 6))
y1 = y[0, :]
y2 = y[1, :]
y3 = y[2, :]
下面我们绘制堆叠条形图,我们通过 bottom
参数来设置条形图的底部坐标。
ax.bar(x, y1)
ax.bar(x, y2, bottom=y1)
ax.bar(x, y3, bottom=(y1 + y2))
fig
ax.clear()
条形图与折线图的综合应用
我们经常会碰到如下情况:需要对比两个不在同一数量级的量。这个时候我们经常用一张图、两个纵坐标轴的方法来绘图。数据如下:
x = np.arange(1, 7)
y1 = np.abs(np.random.rand(6))
y2 = np.abs(100 * np.random.rand(6))
使用 Axes
对象的 twinx
方法可以让返回的新 Axes
对象和原来的 Axes
对象共用同一个 $x$ 轴。
ax_t = ax.twinx()
两个的 Axes
对象分别绘制条形图和折线图。我们希望折线图显示在条形图的上方,故使用 zorder
参数。
ax.bar(x, y1, zorder=1)
ax_t.plot(x, y2, zorder=1, linewidth=2, marker='^', color='r')
fig