在前面关于 matploblib 的文章中,笔者分别介绍了:
本篇介绍 matplotlib 绘制柱状图的方法,包括简单柱状图和复杂柱状图的绘制。简单柱状图包括简单常用的单/多个柱状图绘制;复杂柱状图包括:添加折线柱状图、(水平)并列柱状图、正负柱状图和堆叠柱状图。
柱状图是一种用矩形柱表示数据分类的图表,可以垂直绘制,也可以水平绘制,它的高度与其所表示的数值成正比关系。柱状图显示了不同类别之间的比较关系,图表的 X 轴表示被比较的类别,是离散的, Y 轴则表示具体的类别数据,水平柱状图 X 轴 Y 轴正好反过来。
Matplotlib 提供了 bar() 函数来绘制柱状图,它可以应用在 MATLAB 样式以及面向对象的绘图方法中。当它与 axes 对象一起使用时,其语法格式如下:
axes.bar(x, height, width=0.8, bottom, align='center', **kwargs)
代码示例:
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
fig = plt.figure('Bar example 1', figsize=(9.5, 6.7))
ax1 = fig.add_subplot(221)
ax1.bar(x=0, height=12, width=0.8, color='g', edgecolor='r', linestyle='-.', linewidth=4)
# 单个柱状图,指定了柱状图的 x 坐标位置、高度、宽度、颜色、边框颜色、边框线型、边框线宽
ax2 = fig.add_subplot(222)
y = [7, 4, 5.5, 6, 3.2]
for i in range(len(y)):
ax2.bar(i, y[i]) # 用 for 循环绘制多个柱状图,自动使用了不同颜色
ax3 = fig.add_subplot(223)
y = [9, 39, 15.5, 24, 31]
x = ['20%d年' % n for n in range(10, 10+len(y))]
ax3.bar(x, y) # 一次性绘制多个柱状图
ax3.grid(axis='y') # 增加 y 轴网格线
ax4 = fig.add_subplot(224)
x_data = ['工厂','学校','医院','码头','CBD']
count = [24, 18, 32, 5, 12]
ax4.bar(x_data, count, color='c', hatch='o') # 指定了柱状图的颜色和填充
plt.show()
这里的复杂柱状图是相对上述而言的,实际应用也很常见,主要包括:添加折线柱状图、(水平)并列柱状图、正负柱状图和堆叠柱状图。这里的水平柱状图 barh() 其实就是 bar(orientation=‘horizontal’),参数基本是一致的,折线的绘制方法在上一篇文章中已介绍。
代码示例:
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
fig = plt.figure('Bar example 2', figsize=(8.5, 6.8))
# 添加折线柱状图
ax1 = fig.add_subplot(221)
y_data = [150, 200, 100, 180, 250]
x_data = ["20%d年"%i for i in range(16, 16+len(y_data))]
ax1.plot(x_data, y_data, "b--") # 绘制线图,蓝色虚线
ax1.bar(x_data, y_data, color="r", alpha=0.7) # 绘制柱状图,红色,透明度为0.7
for i,j in zip(x_data, y_data):
ax1.text(i, j+0.05, "%d"%j, ha="center", va="bottom") # 在柱状图上加文字,显示数据
ax1.set_title("成本分析")
ax1.set_xlabel("年份")
ax1.set_ylabel("成本")
# (水平)并列柱状图
ax2 = fig.add_subplot(222)
y1_data = np.array([200, 190, 140, 330])
y2_data = np.array([250, 290, 170, 210])
x_data = ["20%d年"%i for i in range(16, 16+len(y1_data))]
h = 0.4 # 柱状图的宽度
x1 = np.arange(len(x_data)) # 并列柱状图的 x 坐标
x2 = x1 + h # 同上
ax2.barh(x1, y1_data, color="m", height=h) # 绘制水平柱状图,指定坐标、颜色和宽度
ax2.barh(x2, y2_data, color="c", height=h) # 同上
ax2.set_yticks([i+h/2 for i in range(len(x_data))], x_data) # 指定 y 轴刻度值及坐标位置
ax2.legend(labels=('产品A','产品B'))
ax2.set_title("销量分析")
ax2.set_ylabel("年份")
ax2.set_xlabel("销量")
# 正负柱状图
ax3 = fig.add_subplot(223)
ax3.spines["bottom"].set_position(('data', 0)) # 设置坐标轴位置
ax3.bar(x_data, y1_data, color="r", width=0.4, label="产品A") # 绘制柱状图,指定颜色、宽度、标签
ax3.bar(x_data, -y2_data, color="b", width=0.4, label="产品B") # 同上
for i,j in zip(x_data, y1_data):
plt.text(i, j, "%d"%j, ha="center", va="bottom") # 在柱状图上加文字,显示数据
for i2,j2 in zip(x_data, y2_data):
plt.text(i2, -j2, "%d"%j2, ha="center", va="top") # 同上
ax3.legend()
# 堆叠柱状图
ax4 = fig.add_subplot(224)
teams = ['一队', '二队', '三队', '四队', '五队']
bronze = np.array([31, 17, 26, 19, 15])
silver = np.array([37, 23, 18, 18, 10])
gold = np.array([10, 27, 26, 19, 17])
tn = np.arange(len(teams))
ax4.bar(tn, gold, width=0.5, label='金牌', color='gold', bottom=silver+bronze)
ax4.bar(tn, silver, width=0.5, label='银牌', color='silver', bottom=bronze)
ax4.bar(tn, bronze, width=0.5, label='铜牌', color='#CD853F')
ax4.legend(loc="upper right")
ax4.set_xticks(tn, teams) # 指定 x 轴刻度
ax4.set_xlabel("参赛队")
ax4.set_ylabel("奖牌数")
ax4.set_title("奖牌榜")
fig.tight_layout(pad=1, h_pad=1, w_pad=1) # 调整各子图布局,使互不重叠
plt.show()