第八章、使用 matplotlib 绘制高级图表

学习目标
★了解常见的高级图表
★掌握高级图表的绘制方法
matplotlib 除了可以绘制简单的图表,还可以绘制一些常见的高级图表,包括等高线图、
矢量场流线图、棉棒图、哑铃图、甘特图、人口金字塔图、漏斗图、桑基图、树状图和华夫饼图。

下面将对 matplotlib 中绘制高级图表的相关知识进行详细介绍。

8.1 绘制等高线图
等高线图是地形图上高程相等的相邻各点所连成的闭合曲线,它会将地面上海拔高度相
同的点连成环线,之后将环线垂直投影到某一水平面上,并按照一定的比例缩绘到图纸上,
常见于山谷、山峰或梯度下降算法的场景。例如,某座山的等高线图如图 8-1 所示。 第八章、使用 matplotlib 绘制高级图表_第1张图片
图 8-1 的等高线中标注的数字代表海拔高度。等高线图包含 3 个主要的信息,分别为坐
标点的 x 值、 y 值及高度。假设坐标点的高度为 h ,则 h x y 之间的关系如下所示 :
h =(1 x /2+ x 5 + y 3 )e x 2 y 2
在 matplotlib 中,pyplot 可以使用 contour()、contourf() 函数分别绘制和填充等高线图。
contour() 函数的语法格式如下所示 :
contour([X, Y,]Z, [levels,] ** kwargs)
该函数的常用参数的含义如下。

·X,Y :表示坐标点的网格数据。

·Z :表示坐标点对应的高度数据。
·levels :表示等高线的数量。若 levels 为 n ,则 说明绘制 n + 1 条等高线。
·colors :表示不同高度的等高线颜色。
·cmap :表示颜色映射表。
·linewidths :表示等高线的宽度。
·linestyles :表示等高线的线型。
需要注意的是,参数 X、Y 需要接收网格数据,即以坐标矩阵批量描述点的位置。
numpy 模块的 meshgrid() 函数可以生成网格数据。contourf() 与 contour() 函数的参数相似,此
处不再赘述。
此外,Axes 类的对象也可以使用 contour()、contourf() 方法绘制和填充等高线图。
下面使用 numpy 生成一组位于 -2 ~ 2 之间的样本数据,计算出等高线的高度,绘制并
填充等高线图,示例代码如下。
In [1]:
import numpy as np
import matplotlib.pyplot as plt
# 计算高度
def calcu_elevation(x1, y1):
   h = (1-x1/2 + x1 ** 5 + y1 ** 3) * np.exp(-x1 ** 2 - y1 ** 2)
   return h
n = 256
x = np.linspace(-2, 2, n)
y = np.linspace(-2, 2, n)
# 利用 meshgrid() 函数生成网格数据
x_grid, y_grid = np.meshgrid(x, y)
fig = plt.figure()
ax = fig.add_subplot(111)
# 绘制等高线
con = ax.contour(x_grid, y_grid, calcu_elevation(x_grid, y_grid),
    8, colors='black')
# 填充等高线的颜色
ax.contourf(x_grid, y_grid, calcu_elevation(x_grid, y_grid),
8, alpha=0.75, cmap=plt.cm.copper)
# 为等高线添加文字标签
ax.clabel(con, inline=True, fmt='%1.1f', fontsize=10)
ax.set_xticks([])
ax.set_yticks([])
plt.show()
以上示例首先定义了一个计算等高线高度的 calcu_elevation() 函数,其次生成了一组样本
数据,并将这些数据转换为网格数据,然后分别调用 contour() 和 contourf() 方法绘制和填充等
高线,最后调用 clabel() 方法为等高线添加标注,以及隐藏 x 轴和 y 轴的刻度。
运行程序,效果如图 8-2 所示。 第八章、使用 matplotlib 绘制高级图表_第2张图片

8.2 绘制矢量场流线图

矢量场流线图可以表现矢量场的流态,常见于科学和自然学科中的磁场、万有引力和流

体运动等场景。例如,某磁场的流线图如图 8-3 所示。 第八章、使用 matplotlib 绘制高级图表_第3张图片
由图 8-3 可知,矢量场流线图包含多条带有箭头的线条,其中线条的长度表示矢量场的
强度,箭头的方向表示矢量场的方向。此外,矢量场的强度也可以用线条的密度来表示。
在 matplotlib 中,pyplot 可以使用 streamplot() 函数绘制矢量场流线图。streamplot() 函数的
语法格式如下所示 :
streamplot(x, y, u, v, density=1, linewidth=None, col=None, cmap=None,
norm=None, arrowsize=1, arrowstyle='-|>', minlength=0.1,

transform=None, zorder=None, start_points=None, maxlength=4.0,

integration_direction='both', * , data=None)
该函数常用参数的含义如下。
·x,y :表示间距均匀的网格数据。
·u,v :表示 (x,y) 速率的二维数组。
·density :表示流线的密度。
·linewidth :表示流线的宽度。
·arrowsize :表示箭头的大小。
·arrowstyle :表示箭头的类型。
·minlength :表示流线的最小长度。
·maxlength :表示流线的最大长度。
此外,Axes 类的对象也可以使用 streamplot() 方法绘制矢量场流线图。
下面根据一组模拟某磁场的网格数据绘制一个矢量场流线图,示例代码如下。
In [2]:
import numpy as np
import matplotlib.pyplot as plt
y, x = np.mgrid[0:5:50j, 0:5:50j]
u = x
v = y
fig = plt.figure()
ax = fig.add_subplot(111)
# 绘制矢量场流线图
ax.streamplot(x, y, u, v)
plt.show()
运行程序,效果如图 8-4 所示。 第八章、使用 matplotlib 绘制高级图表_第4张图片

 由图 8-4 可知,右侧的流线密度较大,说明该处磁场较强。

8.3 绘制棉棒图
棉棒图亦称为火柴杆图、大头针图或棒棒糖图,由线段(茎)与标记符号(茎头,默认
为圆点)连接而成。其中,线段表示数据点到基线的距离,标记符号表示数据点的数值。棉
棒图是柱形图或条形图的变形,主要用于比较标记符号的相对位置,而非比较线段的长度。
例如,某公司全年盈利情况的棉棒图如图 8-5 所示。 第八章、使用 matplotlib 绘制高级图表_第5张图片
在 matplotlib 中,pyplot 可以使用 stem() 函数绘制棉棒图。stem() 函数的语法格式如下
所示 :
stem([x,] y, linefmt=None, markerfmt=None, basefmt=None, bottom=0,
label=None, use_line_collection=False, data=None)
该函数常用参数的含义如下。
·x,y :表示茎的 x 值和茎头的 y 值。
·linefmt :表示茎属性的字符串。
·markerfmt :表示茎头属性的字符串。
·basefmt :表示基线属性的字符串。
·bottom :表示基线的 y 值。
·label :表示应用于图例的标签。
·use_line_collection :若设为 True,则将棉棒图的所有线段存储到一个 LineCollection 类
对象中 ;若设为 False,则将棉棒图的所有线段存储到列表中。
stem() 函数会返回一个形如 (markerline, stemlines, baseline) 的元组,其中元组的第 1 个元
素 markerline 为代表棉棒图标记的 Line2D 对象,第 2 个元素 stemlines 为代表棉棒图线段的
Line2D 对象,第 3 个元素 baseline 为代表基线的 Line2D 对象。
此外,Axes 类的对象也可以使用 stem() 方法绘制棉棒图。
假设汽车生产商生产了一批小型轿车,并测试了这批小型轿车的燃料消耗量,结果如
表 8-1 所示。 第八章、使用 matplotlib 绘制高级图表_第6张图片

第八章、使用 matplotlib 绘制高级图表_第7张图片 注 :表 8-1 中所列轿车的燃料消耗量数据来源于网络,不能确定其真实性。

根据表 8-1 的数据,将“轿车品牌”一列的数据作为 x 轴的标签,将“燃料消耗量”一
列的数据作为 y 轴的数据,使用 stem() 绘制不同品牌轿车燃料消耗量的棉棒图,具体代码如下。
In [3]:
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False
x = np.arange(1, 16)
y = np.array([5.9, 6.2, 6.7, 7.0, 7.0, 7.1, 7.2, 7.4,
         7.5, 7.6, 7.7, 7.7, 7.7, 7.8, 7.9])
labels = np.array([' 宝骏 310', ' 宝马 i3', ' 致享 ', ' 焕驰 ', ' 力帆 530',
' 派力奥 ', ' 悦翔 V3', ' 乐风 RV', ' 奥迪 A1', ' 威驰 FS',
' 夏利 N7', ' 启辰 R30', ' 和悦 A13RS', ' 致炫 ', ' 赛欧 '])
fig = plt.figure(figsize=(10, 6), dpi= 80)
ax = fig.add_subplot(111)
# 绘制棉棒图
markerline, stemlines, baseline = ax.stem(x, y, linefmt='--',
markerfmt='o', label='TestStem', use_line_collection=True)
# 设置棉棒图线段的属性
plt.setp(stemlines, lw=1)
ax.set_title(' 不同品牌轿车的燃料消耗量 ', fontdict={'size':18})
ax.set_ylabel(' 燃料消耗量 (L/km)')
ax.set_xticks(x)

ax.set_xticklabels(labels, rotation=60)

ax.set_ylim([0, 10])
for temp_x, temp_y in zip(x, y):
   ax.text(temp_x, temp_y + 0.5, s='{}'.format(temp_y), ha= 'center',
va='bottom', fontsize=14)
plt.show()
运行程序,效果如图 8-6 所示。 第八章、使用 matplotlib 绘制高级图表_第8张图片

 

图 8-6 中,每个茎头上方都添加了注释文本。由图 8-6 可知,赛欧轿车的燃料消耗量最大,

为 7.9 L/km。

8.4 绘制哑铃图
哑铃图又名 DNA 图(图表横着看像哑铃,竖着看像 DNA),主要用于展示两个数据点之
间的变化。哑铃图可以看作散点图与线形图的组合,适用于比较各种项目“前”与“后”的
位置及项目的等级排序等场景。例如,2017 年与 2018 年某公司各部门活动经费的使用情况
如图 8-7 所示。
已知美国在 2013 年和 2014 年分别对部分城市的人口 PCT 指标进行了统计,并将统计的
结果整理到 health.xlsx 文件中。health.xlsx 文件的内容如图 8-8 所示。 第八章、使用 matplotlib 绘制高级图表_第9张图片

 第八章、使用 matplotlib 绘制高级图表_第10张图片

下面使用 pandas 读取 health.xlsx 文件的数据,并根据读取的数据绘制由散点和线组成的

哑铃图,示例代码如下。
In [4]:
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.lines as mlines
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False
df = pd.read_excel(r"C:\Users\admin\Desktop\health.xlsx")
df.sort_values('pct_2014', inplace=True)
df.reset_index(inplace=True)
df = df.sort_values(by="index")
def newline(p1, p2, color='black'):

  ax = plt.gca()  # 获取当前的绘图区域

  l = mlines.Line2D([p1[0], p2[0]], [p1[1],p2[1]], color='skyblue')
   ax.add_line(l)
   return l
fig, ax = plt.subplots(1, 1, figsize=(8, 6))
# 绘制散点
ax.scatter(y=df['index'], x=df['pct_2013'], s=50,
color='#0e668b', alpha=0.7)
ax.scatter(y=df['index'], x=df['pct_2014'], s=50,
color='#a3c4dc', alpha=0.7)
# 绘制线条
for i, p1, p2 in zip(df['index'], df['pct_2013'], df['pct_2014']):
   newline([p1, i], [p2, i])
ax.set_title("2013 年与 2014 年美国部分城市人口 PCT 指标的变化率 ", fontdict={'size':12})
ax.set_xlim(0, .25)
ax.set_xticks([.05, .1, .15, .20])
ax.set_xticklabels(['5%', '10%', '15%', '20%'])
ax.set_xlabel(' 变化率 ')
ax.set_yticks(df['index'])
ax.set_yticklabels(df['city'])
ax.grid(alpha=0.5, axis='x')
plt.show()
运行程序,效果如图 8-9 所示。 第八章、使用 matplotlib 绘制高级图表_第11张图片

第八章、使用 matplotlib 绘制高级图表_第12张图片

图 8-9 中,每个杠铃图形左端的圆点代表 2013 年美国部分城市人口 PCT 指标的变化率,
右端的圆点代表 2014 年美国部分城市人口 PCT 指标的变化率。由图 8-9 可知,洛杉矶市人

口 PCT 指标的变化率最大,圣路易斯市人口 PCT 指标的变化率最小。

8.5 绘制甘特图
甘特图亦称为横道图、条状图,它通过活动列表和时间刻度表示特定项目的顺序与持续
时间。甘特图一般以时间为横轴、项目为纵轴,可以直观地展示每个项目的进展情况,以便
于管理者了解项目的剩余任务及评估工作进度。例如,某公司于 12 月份跟踪了某项目进度,
如图 8-10 所示。 第八章、使用 matplotlib 绘制高级图表_第13张图片

 

观察图 8-10 可知,甘特图类似于条形图,它们的图形都是横向的矩形条,但甘特图中
每个矩形条的起始位置是不同的。使用 pyplot 模块的 barh() 函数可以绘制一个甘特图,只需
要给 left 参数传入值,指定每个矩形条 x 坐标值即可。
已知某公司准备开辟一个新项目,为确保项目的可行性,将该项目划分为“项目确定”“问
卷设计”“试访”“问卷确定”“实地执行”“数据录入”“数据分析”“报告提交”共 8 个任务,
并指定了各任务的周期。下面使用 barh() 绘制一个甘特图,示例代码如下。
In [5]:
import numpy as np
import matplotlib.pyplot as plt
ticks = np.array([' 报告提交 ', ' 数据分析 ', ' 数据录入 ', ' 实地执行 ',
     ' 问卷确定 ', ' 试访 ', ' 问卷设计 ', ' 项目确定 '])
y_data = np.arange(1, 9)
x_data = np.array([0.5, 1.5, 1, 3, 0.5, 1, 1,2])
fig,ax = plt.subplots(1, 1)
ax.barh(y_data, x_data, tick_label=ticks,
   left=[7.5, 6, 5.5, 3, 3, 2, 1.5, 0], color='#CD5C5C')
[ax.spines[i].set_visible(False) for i in ['top', 'right']]
ax.set_title(" 任务甘特图 ")
ax.set_xlabel(" 日期 ")
ax.grid(alpha=0.5, axis='x')
plt.show()
运行程序,效果如图 8-11 所示。
图 8-11 中,每个深灰色的条形代表任务的周期,条形越长代表周期越长。由图 8-11 可知,“实地执行”任务的周期最长,共计 3 天。 第八章、使用 matplotlib 绘制高级图表_第14张图片

 

你可能感兴趣的:(Python数据可视化,matplotlib,python)