Matplotlib 3.0 秘籍(三)
二、基本绘图入门
在本章中,我们将介绍绘制以下图形的方法:
- 线形图
- 条形图
- 散点图
- 气泡图
- 堆叠图
- 饼图
- 表格图
- 极坐标图
- 直方图
- 箱形图
- 提琴图
- 热图
- Hinton 图
- 图像
- 等高线图
- 三角剖分
- 流图
- 路径
介绍
一幅图片价值一千个单词,数据的可视化在寻找数据中的隐藏图案方面起着至关重要的作用。 在一段时间内,已开发出各种图形来表示不同类型变量之间的不同关系。 在本章中,我们将看到如何在不同的上下文中使用这些不同的图以及如何使用 Matplotlib 绘制它们。
线形图
线形图用于表示两个连续变量之间的关系。 它通常用于表示随时间变化的趋势,例如季度和年度的 GDP 增长率,通货膨胀,利率和股票价格。 我们在第 1 章“Matplotlib 剖析”中看到的所有图形都是线形图的示例。
准备
我们将使用 Google 股票价格数据绘制时间序列线形图。 我们将数据(日期和每日收盘价,用逗号分隔)保存在没有标题的.csv文件中,因此我们将使用 Pandas 库进行读取并将其传递给matplotlib.pyplot函数以绘制图形。
现在,使用以下代码导入所需的库:
import matplotlib.pyplot as plt
import pandas as pd
操作步骤
以下代码绘制了 Google 股票价格的时间序列图:
- 将
Google Stock Price文件(日期和价格)加载到 x,y 坐标中:
stock = pd.read_csv('GOOG.csv', header=None, delimiter=',')
- 添加列名:
stock.columns = ['date','price']
- 将 pandas 数据帧转换为时间序列:
stock['date'] = pd.to_datetime(stock['date'], format='%d-%m-%Y')
- 将日期设置为 Pandas 数据帧的索引:
indexed_stock = stock.set_index('date')
ts = indexed_stock['price']
- 绘制图形:
plt.plot(ts)
- 在屏幕上显示图形:
plt.show()
工作原理
以下是代码的说明:
pd.read_csv()函数指定以下内容:header=None,输入文件没有标题delimiter=',',date和price用逗号(,)分隔- 将数据读入
stock数据帧
stock.columns命令为stock数据帧中的每个属性date和price分配名称。pd.to_datetime()函数将日期从字符格式转换为日期时间格式。 格式:%d-%m-%Y参数指定输入文件中日期的格式。stock.set_index()将date列设置为索引,以便price列可以表示时间序列数据,plot命令可以理解。
下图是您应该从前面的代码块获得的输出:
更多
除了从.csv或.xlsx文件中读取 Google 股票价格数据之外,还有一些标准 API,例如fix_yahoo_finance和pandas_datareader可以直接从打开的数据库中读取数据。
Standard APIs undergo frequent changes and at times the database websites are not responsive. You need to install these APIs on your machine, as they don't come with standard Python distributions.
在这里,我们将展示一个使用fix_yahoo_finance的示例:
- 导入所需的库:
import matplotlib.pyplot as plt
import pandas as pd
import fix_yahoo_finance as yf
- 下载从 2017 年 10 月 1 日至 2018 年 1 月 1 日的
AAPL每日收盘价:
data = yf.download('AAPL','2017-10-01','2018-01-01')
- 按日期绘制收盘价(
Close)。 请注意,此处date是默认的 x 轴,因为yf.download创建具有date索引的数据。 因此,我们不需要为绘图提供 x 轴坐标。 请注意,这里我们使用的是plot()Pandas 命令,而不是 Matplotlib:
data.Close.plot()
- 在屏幕上显示图形:
plt.show()
您应该看到一个图形,就像这里描述的那样:
您可以尝试使用pandas_datareader API。 有关更多详细信息,请参考这个页面上的文档。
条形图
条形图是使用条形图比较不同类别数据的图形。 根据分类变量使用哪个轴,可以垂直或水平显示条形图。 假设我们有的数据,即在一年的时间内在冰淇淋店每月售出的冰淇淋数量。 我们可以使用条形图对此进行可视化。
准备
我们将使用 Python calendar包将数字月份(1 到 12)映射到相应的描述月份(1 月到 12 月)。
在绘制图形之前,我们需要导入必要的包:
import matplotlib.pyplot as plt
import numpy as np
import calendar
操作步骤
以下代码绘制了条形图:
- 设置 x 和 y 轴的数据:
month_num = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
units_sold = [500, 600, 750, 900, 1100, 1050, 1000, 950, 800, 700,
550, 450]
- 分配空间并指定图形的布局:
fig, ax = plt.subplots()
- 将描述性月份名称设置为 x 轴刻度:
plt.xticks(month_num, calendar.month_name[1:13], rotation=20)
- 绘制条形图:
plot = ax.bar(month_num, units_sold)
- 将数据值添加到条形的顶部:
for rect in plot:
height = rect.get_height()
ax.text(rect.get_x() + rect.get_width()/2., 1.002*height,'%d' %
int(height), ha='center', va='bottom')
- 在屏幕上显示图形:
plt.show()
工作原理
这是前面的代码块的说明:
- Matplotlib 的较旧版本仅接受浮点数据类型作为其数据参数。 因此,月份必须以数字格式表示。
month_num和units_sold是 Python 列表,表示一年中每个月的销售数量。plt.subplots()允许我们根据图形的数量以及如何在图形中组织图形来定义图形的布局。 我们将在第 3 章“绘制多个图表,子图和图形”和第 6 章“带有高级功能的绘图”中了解更多信息。 在这种情况下,我们使用它来访问要绘制条形图的轴域,以便可以用代表条形图的实际数据对其进行标注。 如果您从第 1 章“Matplotlib 剖析”中回想起,我们已经看到轴域是图形中的单个图。- 将月份格式从数字格式更改为 x 轴上的相应月份名称。
calendar.month_name[1:13]将返回 1 月至 12 月,而plt.xticks()将 x 轴代号从数字 1 到 12,更改为 1 月到 12 月,以提高可读性。 for循环中的ax.text()用其相应的数据值标注每个条。 此函数的参数指定必须在条形图上精确放置数据文本的位置:首先,获取当前条形图的 x 和 y 坐标,然后再添加bar_width / 2到 x 坐标,以及1.002高度到 y 纵坐标;然后,使用va和ha自变量,将文本居中对齐在条形上方:
更多
前一节的条形图垂直绘制条形图。 我们还可以绘制水平条形图,如下所示。 除了plt.xticks()和plt.bar()分别被plt.yticks()和plt.barh()代替外,大多数代码与上一节中使用的代码相同:
## matplotlib accepts only floating point data types as its arguments
for data.
## So months have to be represented in numerical format
month_num = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
units_sold = [500, 600, 750, 900, 1100, 1050, 1000, 950, 800, 700, 550,
450]
fig, ax = plt.subplots()
## change the month number to month name on y axis
plt.yticks(month_num, calendar.month_name[1:13], rotation=20)
## plot horizontal bar graph
plot = plt.barh(month_num, units_sold)
## Display the graph on the screen
plt.show()
这是输出图的外观:
散点图
散点图用于比较两个变量的分布,并查看它们之间是否存在任何相关性。 如果数据中有不同的群集/段,则在散点图中将很清楚。
准备
导入以下库:
import matplotlib.pyplot as plt
import pandas as pd
我们将使用pandas读取 Excel 文件。
操作步骤
以下代码块绘制了一个散点图,描述了年龄和体重之间的关系:
- 将图形大小(宽度和高度)设置为(
10, 6)英寸:
plt.figure(figsize=(10,6))
- 从 Excel 文件中读取年龄和体重数据:
age_weight = pd.read_excel('scatter_ex.xlsx', 'age_weight')
x = age_weight['age']
y = age_weight['weight']
- 绘制散点图:
plt.scatter(x, y)
- 设置 x 和 y 轴标签:
plt.xlabel('Age')
plt.ylabel('Weight)
- 显示图形:
plt.show()
工作原理
该代码的说明如下:
plt.figure(figsize=(10,6))用大小(10, 6)覆盖默认图形大小。pd.read_excel()读取数据,并将值分配给 x 和 y 轴坐标。plt.scatter(x,y)绘制散点图。plt.xlabel()和plt.ylabel()设置 x 和 y 轴标签以提高可读性。
在终端上显示图形。 您应该看到以下图表:
很明显,年龄和体重之间没有关系,因为这些点是分散的。 如果所描绘的两个元素之间存在相关性,我们将观察到直线或曲线的图案。
The previous graphs could have been plotted with the plt.plot() method also. The plt.scatter() method has a lot more flexibility to customize each of the points with different sizes, colors, and so on, which we will observe in the bubble plot section. However, this flexibility comes at the cost of performance. For larger datasets, the plt.plot() method is lot faster than the plt.scatter() method.
更多
在这里,我们将看到另一个散点图示例,在这里我们可以清楚地看到不同的段。
The Iris flower dataset is the oldest dataset, introduced in 1936 by Ronald Fisher. The dataset has 50 examples each of three species of Iris, named Setosa, Virginica, and Versicolor. Each example has four attributes, and the length and width in centimeters of both sepals and petals. This dataset is widely used in machine learning (ML) for classification and clustering. We will use this dataset to demonstrate how a scatter plot can show different clusters within a dataset.
以下代码块绘制了花瓣的长度和宽度的散点图:
- 使用 Pandas 从
.csv文件加载Iris数据集:
iris = pd.read_csv('iris_dataset.csv', delimiter=',')
- 在文件中,每类物种都用描述性名称定义,我们将其映射为
0,1或2的数字代码:
iris['species'] = iris['species'].map({"setosa" : 0, "versicolor" :
1, "virginica" : 2})
- 以 x 轴上的花瓣长度和 y 轴上的花瓣宽度绘制散点图:
plt.scatter(iris.petal_length, iris.petal_width, c=iris.species)
- 标记 x 和 y 轴:
plt.xlabel('petal length')
plt.ylabel('petal width')
- 在屏幕上显示图形:
plt.show()
这是代码的说明:
pd.read_csv()将数据读取到iris数据帧中。- 数据帧中的
species属性具有描述性的类名setosa,versicolor和virginica。 但是,如果我们想用不同的颜色绘制每个类,则传递的参数应该是数字代码。 因此,我们将它们映射到数字代码。 iris['species'] = iris['species'].map()将描述性名称替换为0,1和2数字代码。c=iris.species指定到不同类别的颜色映射。 这些参数类应该是数字的,这是我们之前所做的。plt.scatter()绘制散点图。
您应该在屏幕上看到以下图形:
显然,我们可以在此处看到三个不同的群集。 但是,尚不清楚哪种颜色代表山,杂色和弗吉尼亚簇。 在随后的章节中,我们将看到如何使用标签来区分不同的聚类,在此我们将学习如何自定义图。
气泡图
使用相同的plt.scatter()方法绘制气泡图。 它是散点图的体现,图中的每个点都显示为气泡。 这些气泡中的每一个都可以显示为不同的颜色,大小和外观。
准备
导入所需的库。 我们将使用 Pandas 来读取 Excel 文件:
import matplotlib.pyplot as plt
import pandas as pd
操作步骤
以下代码块绘制了一个气泡图,我们之前已经看到了一个散点图:
- 加载
Iris数据集:
iris = pd.read_csv('iris_dataset.csv', delimiter=',')
- 在文件中,每类物种都定义为
0,1和2,我们将其映射为它们的描述性名称:
iris['species'] = iris['species'].map({"setosa" : 0, "versicolor" :
1, "virginica" : 2})
- 绘制散点图:
plt.scatter(iris.petal_length, iris.petal_width,
s=50*iris.petal_length*iris.petal_width,
c=iris.species,
alpha=0.3)
- 标记 x 和 y 轴:
plt.xlabel('petal length')
plt.ylabel('petal width')
- 在屏幕上显示图形:
plt.show()
工作原理
以下是该代码的说明:
pd.read_csv()读取数据并用数字代码替换描述性名称,如前所述。s = 50 * iris.petal_length * iris.petal_width指定气泡的大小。 它实质上代表了该区域。s公式中使用的常数50是一个随机数,该常数将每个点的面积乘以该常数。 该常数越小,所有点的相对大小将越小。 尝试将此常数从 25 更改为 50,然后更改为 100,然后查看气泡大小如何变化。 如果没有此乘数,则某些点的大小太小而无法在图中观察到它们。c = iris.species在数据中指定不同的类(群集)。pyplot方法使用此方法以不同的颜色表示这些类别中的每一个。alpha=0.3指定气泡的外观,并确定气泡的透明度。 范围是 0 到 1; 如果值接近零,则气泡高度透明;如果值接近 1,则气泡高度不透明:
堆叠图
堆叠图表示线形图下的区域,多条线形图彼此叠放。 它用于提供的可视化,即 y 轴域上绘制的多个变量的累积效果。
我们将通过缺陷原因代码绘制产品缺陷的数量,将三个月堆叠在一起,以给出该季度的累积情况。
准备
导入所需的库:
import numpy as np
import matplotlib.pyplot as plt
操作步骤
以下是绘制堆叠图的步骤:
- 定义图的数据:
x = np.array([1, 2, 3, 4, 5, 6], dtype=np.int32)
Apr = [5, 7, 6, 8, 7, 9]
May = [0, 4, 3, 7, 8, 9]
June = [6, 7, 4, 5, 6, 8]
- 定义要用于图例的
labels列表:
labels = ["April ", "May", "June"]
- 定义图形和轴域:
fig, ax = plt.subplots()
- 绘制
stackplot和legend:
ax.stackplot(x, Apr, May, June, labels=labels)
ax.legend(loc=2)
- 设置标签和标题:
plt.xlabel('defect reason code')
plt.ylabel('number of defects')
plt.title('Product Defects - Q1 FY2019')
- 在屏幕上显示该图:
plt.show()
工作原理
这是代码的说明:
x = np.array([1, 2, 3, 4, 5, 6], dtype=np.int32)是产品缺陷代码的列表,数据类型为整数。Apr = [5, 7, 6, 8, 7, 9]是按缺陷代码分类的 4 月份产品缺陷计数的列表。May = [0, 4, 3, 7, 8, 9]是按月份分类的缺陷代码的产品缺陷计数列表。June = [6, 7, 4, 5, 6, 8]是按月份分类的缺陷代码的产品缺陷计数列表。labels = ["April ", "May", "June"]是用作图例的标签列表。fig, ax = plt.subplots()定义图形和要在其上绘制图形的轴域。ax.stackplot(x, Apr, May, June, labels=labels)绘制具有给定数据和标签的堆叠图。ax.legend(loc=2)指定要在图的左上方绘制的图例; 我们将在第 4 章“开发可视化以提高发布质量”中了解有关图例位置的更多信息。plt.xlabel('defect reason code')绘制 x 轴的标签。plt.ylabel('number of defects')绘制 y 轴标签。plt.title('Product Defects - Q1 FY2019')绘制图形标题。plt.show()在屏幕上显示图形。
在执行前面的代码时,您应该在屏幕上看到下图:
饼图
饼图用于表示各种类别/组对总数的贡献。 例如,每个州对国家 GDP 的贡献,一部电影对一年中发行的电影总数的贡献,学生等级(A,B,C,D 和 E)占总班级人数的百分比 ,或每月家庭支出在杂货,蔬菜,公用事业,服装,教育,医疗保健等方面的分配。
准备
导入所需的库:
import matplotlib.pyplot as plt
操作步骤
以下代码块绘制了一年中发行的电影类型的饼图:
- 设置饼图的数据:
labels = ['SciFi', 'Drama', 'Thriller', 'Comedy', 'Action', 'Romance']
sizes = [5, 15, 10, 20, 40, 10] # Add upto 100%
- 稍微在圆外显示一个切片:
explode = (0, 0, 0, 0, 0.1, 0) # only "explode" the 5th slice (i.e.'Action')
- 绘制饼图:
plt.pie(sizes, labels=labels, explode=explode, autopct='%1.1f%%',
shadow=True, startangle=90)
- 相等的长宽比可确保将饼图绘制为圆形。 默认值为椭圆:
plt.axis('equal')
- 在屏幕上显示图形:
plt.show()
工作原理
以下是代码的说明:
labels和sizes是 Python 列表,代表流派和一年中发行的电影总数的百分比。 输入列表中标签的顺序在饼图中按逆时针方向绘制。explode参数指定要向外展开图表的哪个部分。autopct自变量描述了要在百分比数据点中显示的小数点的数量。 如果省略此参数,则切片将不显示实际百分比(%)数据。shadow参数指定是否应在每个切片上显示阴影。startangle参数指定第一个切片应开始的角度,并且它逆时针旋转以表示饼图中的所有其他切片。plt.pie()绘制饼图。plt.axis(equal)表示图表应显示为圆形(x 和 y 轴相等)。 默认形状是椭圆:
表格图
表格图是条形图和表格的组合,表示相同的数据。 因此,它是图形表示与表格中相应数据的组合。
准备
我们将以每年销售的电池数量为例,不同的安时(Ah)额定值。 有两个类别变量:年份和 Ah 等级,一个数字变量:售出的电池数量。
导入所需的库:
import numpy as np
import matplotlib.pyplot as plt
操作步骤
以下代码块绘制了一张表格,列出了每年出售的电池类型:
- 准备数据:
rows = ['2011', '2012', '2013', '2014', '2015']
columns = ('7Ah', '35Ah', '40Ah', '135Ah', '150Ah')
data = [[75, 144, 114, 102, 108], [90, 126, 102, 84, 126],
[96, 114, 75, 105, 135], [105, 90, 150, 90, 75],
[90, 75, 135, 75, 90]]
- 定义 y 轴的范围和比例:
values = np.arange(0, 600, 100)
- 指定要使用的色谱。 每年将以不同的颜色表示:
colors = plt.cm.OrRd(np.linspace(0, 0.5, len(rows)))
- 定义要绘制条形的 x 轴刻度:
index = np.arange(len(columns)) + 0.3
bar_width = 0.5
- 初始化堆叠条形图的垂直偏移量:
y_offset = np.zeros(len(columns))
- 根据图形和轴域指定绘图区域:
fig, ax = plt.subplots()
- 绘制条并为表格创建文本标签。 初始化用于保存表数据的列表:
cell_text = []
for循环的每次迭代都以一种颜色绘制所有电池额定值的一年数据:
n_rows = len(data)
for row in range(n_rows):
plot = plt.bar(index, data[row], bar_width, bottom=y_offset,
color=colors[row])
y_offset = y_offset + data[row]
cell_text.append(['%1.1f' % (x) for x in y_offset])
i=0
## Each iteration of this for loop, labels each bar with
corresponding value for the given year
for rect in plot:
height = rect.get_height()
ax.text(rect.get_x() + rect.get_width()/2, y_offset[i],'%d'
% int(y_offset[i]),
ha='center', va='bottom')
i = i+1
- 在轴域的底部添加一个表格:
the_table = plt.table(cellText=cell_text, rowLabels=rows,
rowColours=colors, colLabels=columns, loc='bottom')
plt.ylabel("Units Sold")
- x 轴上有 n 个刻度,因为此表覆盖了标签:
plt.xticks([])
plt.title('Number of Batteries Sold/Year')
- 在屏幕上显示图:
plt.show()
工作原理
以下是代码的说明:
rows是年份列表,columns是电池额定值列表。 它们以图表中表格的行和列的形式绘制。data是给定年份中每种额定电池的销售数量,例如,2011 年售出 75 单位 7Ah 电池。values是指定 y 轴比例的列表,增量为 100,从零开始,最大为 600。 这是一个堆叠的条形图,它应该涵盖所有年份中给定电池额定值的总和(在这种情况下,最大值为 576)。plt.cm.OrRd()指定强度变化的颜色范围; Matplotlib 中有预定义的颜色表。 我们将在第 4 章“开发可视化来提高发布质量”中介绍这些内容。 在这里,它用于以不同的颜色显示每年的数据。index指定每个条形在 x 轴上的位置,bar_width指定每个条形的宽度。y_offset表示每年的数据应在 y 轴上的起始位置,因为每年的数据彼此堆叠。 从底部开始,从零开始,然后每年继续增加。- 当启动
for循环时,每次迭代都会绘制给定年份所有电池额定值的条形,然后再进行另一个for循环以用相应的数据标签标注每个条形。 - 第二个
for循环中的参数指定将数据文本放置在小节上方的确切位置。 首先,获取当前条形 x 和 y 坐标,然后将bar_width/2添加到 x 坐标,然后y_offset[i]给我们 y 座标; 然后,使用va和ha,参数将文本在条上居中对齐。 - 然后添加
Y-label,标题和掩码X-ticks。
这是绘图的样子:
极坐标图
极坐标图是在极坐标轴域上绘制的图表,其坐标为角度(以度为单位)和半径,与 x 和 y 的笛卡尔系统相对。 我们将以组织中各个部门产生的计划支出与实际支出为例。 这也称为蜘蛛网图。
准备
导入所需的库:
import numpy as np
import matplotlib.pyplot as plt
操作步骤
Since it is a circular spider web, we need to connect the last point to the first point, so that there is a circular flow of the graph. To achieve this, we need to repeat the first department data point at the end of the list again. Hence, in the following example, 30 and 32 (the first entry in each of the lists) are repeated at the end again.
以下代码块绘制了一个极坐标图并将其显示在屏幕上:
- 设置极坐标图的数据:
Depts = ["COGS","IT","Payroll","R & D", "Sales & Marketing"]
rp = [30, 15, 25, 10, 20, 30]
ra = [32, 20, 23, 11, 14, 32]
theta = np.linspace(0, 2 * np.pi, len(rp))
- 通过设置图形大小和极坐标投影来初始化蜘蛛图:
plt.figure(figsize=(10,6))
plt.subplot(polar=True)
- 排列网格线以与每个部门名称对齐:
(lines,labels) = plt.thetagrids(range(0,360, int(360/len(Depts))),
(Depts))
- 绘制计划支出图,这是极坐标上的折线图,然后填充其下的区域:
plt.plot(theta, rp)
plt.fill(theta, rp, 'b', alpha=0.1)
- 绘制实际支出图,这是极坐标上的折线图:
plt.plot(theta, ra)
- 为图添加图例和标题:
plt.legend(labels=('Plan','Actual'),loc=1)
plt.title("Plan vs Actual spend by Department")
- 在屏幕上显示图:
plt.show()
工作原理
以下是代码的说明:
Depts是组织中部门的列表。rp和ra是按部门列出的计划支出和实际支出的列表。plt.figure(figsize=(10,6))设置图形大小。plt.subplot(polar=True)设置极性投影。pyplot方法仅接受弧度作为输入,因此我们需要将2 * np.pi(相当于 360 度)弧度平均划分为多个部门,以获取每个部门的角度坐标。np.linspace(0, 2 * np.pi, len(rp))执行此计算。
While the coordinates need to be given in radians, the degree equivalent is easy for visualization. To convert radians to degrees, you can use np.degrees (theta).
- 极角投影上的默认网格线为 45 度(360 度分为八个相等的部分,每个部分 45 度)。 由于我们的部门较少(只有五个),因此需要将网格数限制为部门数。
plt.thetagrids(range(0,360, int(360/len(Depts))), (Depts))函数创建网格并用部门名称标记它们。 如果需要,此函数还返回可以随后使用的行和标签对象。plt.plot(theta, rp)绘制计划费用,并使用plt.fill(theta, rp, 'b', alpha=0.1)用蓝色填充区域。plt.plot(theta, ra),绘制实际费用而未填充其下的区域。
最后,在图上添加标题和图例。 您应该看到以下图表:
更多
在此示例中,我们使用了折线图。 极坐标投影也可以用于散点图,气泡图和条形图。 这只是另一个坐标系,每个点都需要转换为极坐标。
直方图
直方图用于绘制连续变量的分布。 连续变量值分为所需的仓数,并绘制在 x 轴上,落在每个仓中的值计数绘制在 y 轴上。 在 y 轴上,我们也可以绘制总数的百分比来代替计数,在这种情况下,它表示概率分布。 该图通常用于统计分析。
准备
我们将使用有关横向培训计划参与者先前工作经验的数据示例。 经验以年数衡量。
导入所需的库:
import matplotlib.pyplot as plt
import numpy as np
操作步骤
以下代码绘制了经验数据的直方图:
- 创建一个 NumPy 数组,其中包含横向培训班的参与者的工作经验(以年为单位):
grp_exp = np.array([12, 15, 13, 20, 19, 20, 11, 19, 11, 12, 19, 13, 12,
10, 6, 19, 3, 1, 1, 0, 4, 4, 6, 5, 3, 7, 12, 7, 9,
8, 12, 11, 11, 18, 19, 18, 19, 3, 6, 5, 6, 9, 11,
10, 14, 14, 16, 17, 17, 19, 0, 2, 0, 3, 1, 4, 6,
6, 8, 7, 7, 6, 7, 11, 11, 10, 11, 10, 13, 13, 15,
18, 20, 19, 1, 10, 8, 16, 19, 19, 17, 16, 11, 1,
10, 13, 15, 3, 8, 6, 9, 10, 15, 19, 2, 4, 5, 6, 9,
11, 10, 9, 10, 9, 15, 16, 18, 13])
- 绘制分组经验的分布图:
nbins = 21
n, bins, patches = plt.hist(grp_exp, bins = nbins)
- 添加图的轴标签和标题:
plt.xlabel("Experience in years")
plt.ylabel("Frequency")
plt.title("Distribution of Experience in a Lateral Training
Program")
- 以平均经验在图中绘制红色垂直线:
plt.axvline(x=grp_exp.mean(), linewidth=2, color = 'r')
- 在屏幕上显示图:
plt.show()
工作原理
以下是代码的说明:
grp_exp是一个 NumPy 数组,其中包含多年的经验数据。- 通过指定
nbins = 21将此数据分为 21 个大小相等的桶。 plt.hist()以grp_exp和nbins作为参数绘制直方图。 它返回三个参数n,bins和patches。n是包含的列表,每个箱中有个项目;bins是另一个指定箱的起点的列表,patches是每个箱中的对象的列表。 这些可以在程序的后面用于任何其他目的。- 在屏幕上显示直方图之前,添加标题以及 x 和 y 轴标签。
plt.axvline()在数据的平均值处绘制一条垂直线,仅表示平均值在两侧的分布方式。 这是输出的样子:
更多
在 y 轴上,您可以绘制每个仓位中grp_exp列表中的所有条目的总和的百分比,而不是绘制频率, 通过在plt.hist()中指定density=1。 您还可以使用,数据的均值和标准差绘制近似正态分布,以查看此分布遵循正态分布的程度:
- 创建一个 NumPy 数组,其中包含横向培训班的参与者的工作(年):
grp_exp = np.array([12, 15, 13, 20, 19, 20, 11, 19, 11, 12, 19, 13,
12, 10, 6, 19, 3, 1, 1, 0, 4, 4, 6, 5, 3, 7, 12,
7, 9, 8, 12, 11, 11, 18, 19, 18, 19, 3, 6, 5, 6,
9, 11, 10, 14, 14, 16, 17, 17, 19, 0, 2, 0, 3,
1, 4, 6, 6, 8, 7, 7, 6, 7, 11, 11, 10, 11, 10,
13, 13, 15, 18, 20, 19, 1, 10, 8, 16, 19, 19,
17, 16, 11, 1, 10, 13, 15, 3, 8, 6, 9, 10, 15,
19, 2, 4, 5, 6, 9, 11, 10, 9, 10, 9, 15, 16, 18,
13])
- 绘制经验分布图:
nbins = 21
n, bins, patches = plt.hist(grp_exp, bins = nbins, density=1)
- 添加轴标签:
plt.xlabel("Experience in years")
plt.ylabel("Percentage")
plt.title("Distribution of Experience in a Lateral Training
Program")
- 计算
grp_exp数据的平均值(mu)和标准差(sigma):
mu = grp_exp.mean()
sigma = grp_exp.std()
- 为计算出的
mu和sigma添加一条最适合正态分布的线:
y = ((1 / (np.sqrt(2 * np.pi) * sigma)) * np.exp(-0.5 * (1 / sigma
* (bins - mu))**2))
plt.plot(bins, y, '--')
- 在屏幕上显示图:
plt.show()
输出图如下所示:
显然,数据没有遵循正态分布,因为在正态曲线的最佳拟合的上方或下方有太多的条带。
箱形图
箱形图用于可视化连续变量的描述统计量。 它直观地显示了第一个和第三个四分位数,中值(平均值)和胡须是四分位数范围(IQR)的 1.5 倍 -- 第三个和第一个四分位数之间的差异是离群值。 第一个四分位数(矩形框的底部)标记了一个点,低于该点的总数下降 25%。 第三四分位数(矩形框的顶部)标记了一个点,低于该点的点数下降 75%。
如果没有异常值,则胡须将显示最小值和最大值。
再次用于统计分析。
准备
我们将在此示例中使用葡萄酒质量数据集的示例。 我们将考虑三个属性:alcohol,fixed acidity和quality。 通常,针对不同的维度(例如地理或时间)绘制相同的属性,以比较沿这些维度的数据分布。 在这里,我们绘制了三个不同属性的箱形图:
import matplotlib.pyplot as plt
import pandas as pd
操作步骤
以下是绘制三个箱形图的代码块,每个属性一个图:
- 将数据从 CSV 文件读取到 Pandas 数据帧中:
wine_quality = pd.read_csv('winequality.csv', delimiter=';')
- 使用
Wine Quality数据集创建的三个属性的data列表:
data = [wine_quality['alcohol'], wine_quality['fixed acidity'],
wine_quality['quality']]
- 绘制箱形图:
plt.boxplot(data)
- 在屏幕上显示图:
plt.show()
工作原理
plt.boxplot()是绘制箱形图的方法。data参数可以是一个或多个属性的列表。 默认情况下,每个框中的黄线代表属性的中值(也可以更改为平均值)。 底部胡须距离盒子底线 1.5 IQR,顶部胡须顶部盒子上方 1.5 IQR。 框的底行是的第一个四分位数,框的的上一行是数据的第三个四分位数。- 胡须上方和下方的点是异常值。 在第一箱和第二箱图中,在底部胡须以下没有离群值,而所有三个离群值顶部胡须之上:
更多
在plt.boxplot()中,通过指定showfliers=False自变量 ,您可以抑制离群值,因此仅在两侧的胡须上绘图。 通过指定vert=False自变量 ,您可以水平绘制箱形图,还可以自定义具有不同形状和颜色的离群值:
plt.boxplot(data, vert=False, flierprops=dict(markerfacecolor='r',
marker='D'))
plt.show()
您应该看到以下输出:
提琴图
提琴图是直方图和箱形图的组合。 它提供有关数据完整分布的信息,以及均值/中值,最小值和最大值。
准备
在此示例中,我们还将使用与和箱形图相同的数据。
导入所需的库:
import matplotlib.pyplot as plt
import pandas as pd
操作步骤
以下是绘制提琴图的代码块:
- 将数据从 CSV 文件读取到 Pandas 数据帧中:
wine_quality = pd.read_csv('winequality.csv', delimiter=';')
- 准备
wine_quality的三个属性的列表:
data = [wine_quality['alcohol'], wine_quality['fixed acidity'],
wine_quality['quality']]
- 绘制提琴图:
plt.violinplot(data, showmeans=True)
- 在屏幕上显示图:
plt.show()
工作原理
这是代码的说明:
plt.violinplot()绘制提琴图。 底部胡须是最小值,是顶部胡须是最大值,水平线在是平均值。 在的两侧,垂直线是代表和数据实际分布的数据直方图。 通过将showmeans=True替换为showmedian=True,我们可以用一条横线代表数据的中位数,而不是表示的意思:
读取和显示图像
Matplotlib.pyplot具有使我们能够读取.jpeg和.png图像并将它们转换为像素格式以显示为图像的函数。
准备
导入所需的库:
import matplotlib.pyplot as plt
操作步骤
这是读取 JPEG 文件作为像素值列表并将其显示为屏幕上的图像的代码块:
- 将图像
louvre.jpg读入三维数组(彩色图像具有三个通道,而黑白图像仅具有一个通道):
image = plt.imread('louvre.jpg')
- 打印图像的大小:
print("Dimensions of the image: ", image.shape)
- 绘制图像:
plt.imshow(image)
- 在屏幕上显示图像:
plt.show()
工作原理
plt.imread()方法将图像读取为像素数组。plt.imshow()方法在屏幕上显示图像。image.shape给出读取图像的列表的大小。print()在屏幕上显示图像的大小。
热图
热图用于以不同的强度可视化不同颜色的数据范围。 在这里,我们以绘制相关矩阵作为热图为例。 相关矩阵的元素指示两个变量之间的线性关系的强度,并且矩阵包含给定数据中属性的所有组合的此类值。 如果数据具有五个属性,则相关矩阵将是5 x 5矩阵。
准备
在此示例中,我们还将使用“葡萄酒质量”数据集。 它具有 12 个不同的属性。 我们将首先获得一个相关矩阵,然后将其绘制为热图。 目前尚无热图函数/方法,因此我们将使用和相同的imshow方法来读取和显示图像。
导入所需的库:
import matplotlib.pyplot as plt
import pandas as pd
操作步骤
以下是绘制和相关矩阵的热图的代码块:
- 将数据从 CSV 文件读取到 Pandas 数据帧中:
wine_quality = pd.read_csv('winequality.csv', delimiter=';')
- 获得
wine_quality所有属性的相关矩阵:
corr = wine_quality.corr()
- 指定图形大小:
plt.figure(figsize=(12,9))
- 绘制热图:
plt.imshow(corr,cmap='hot')
- 绘制颜色条来映射哪种颜色代表哪些数据值:
plt.colorbar()
- 标签, x 和 y 轴刻度。 显示旋转度为
20的 x 轴标签:
plt.xticks(range(len(corr)),corr.columns, rotation=20)
plt.yticks(range(len(corr)),corr.columns)
- 在屏幕上显示图:
plt.show()
工作原理
以下是代码的说明:
wine_quality.corr()方法返回数据集中所有属性的相关矩阵。- 相关值的范围从 -1(高度负)到 +1(高度正)。 负值从红色到黑色表示,正值从深黄色到白色表示。 纯白色是+1,这是最高的正相关,而纯黑色是最高的负相关。
- 不出所料,所有对角线框都是白色的,因为它们彼此相关,必须为 +1。 pH 和固定酸度值之间的相关性为黑色,这表示高度负值,接近 -1
我们得到的输出如下:
Hinton 图
Hinton 图是一个二维图,用于可视化深度学习应用中的权重矩阵。 Matplotlib 没有直接的方法来绘制此图。 因此,我们将不得不编写代码来对此进行绘制。 权重矩阵取自和机器学习算法之一,该算法对图像进行分类。
准备
导入所需的库:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
操作步骤
以下代码块定义了该函数并调用了该函数以绘制 Hinton 图:
- 从 Excel 文件中读取重量矩阵数据:
matrix = np.asarray((pd.read_excel('weight_matrix.xlsx')))
- 实例化图形和轴域:
fig, ax = plt.subplots()
- 为轴域设置参数:
ax.patch.set_facecolor('gray')
ax.set_aspect('equal', 'box')
ax.xaxis.set_major_locator(plt.NullLocator())
ax.yaxis.set_major_locator(plt.NullLocator())
- 绘制 Hinton 图:
max_weight = 2 ** np.ceil(np.log(np.abs(matrix).max()) / np.log(2))
for (x, y), w in np.ndenumerate(matrix):
color = 'white' if w > 0 else 'black'
size = np.sqrt(np.abs(w) / max_weight)
rect = plt.Rectangle([x - size / 2, y - size / 2], size, size, facecolor=color, edgecolor=color)
ax.add_patch(rect)
ax.autoscale_view()
- 在屏幕上显示:
plt.show()
工作原理
这是代码的说明:
pd.read_excel()将 Excel 文件读入 Pandas 数据帧。np.asarray()根据进一步处理的需要将数据帧转换为 NumPy 数组。 它是20 x 7的矩阵。np.abs()返回作为输入给出的矩阵的绝对值。np.abs(matrix).max()从绝对矩阵返回最大值。np.log()返回所传递参数的自然对数值。- 对于给定的浮点数,
np.ceil()将参数四舍五入到下一个最大值,例如,np.ceil(2.2) = 3.0。 ax.patch.set_facecolor('gray')将每个方框的颜色设置为灰色。ax.set_aspect('equal', 'box')将长宽比(宽高比)和图形上要点的形状指定为方框。ax.xaxis.set_major_locator(plt.NullLocator())将 x 轴刻度设置为空,这样就不会标记任何刻度,也不会放置任何刻度标签。- 启动
for循环以遍历权重矩阵的每个元素,并将颜色设置为白色(正值),黑色(负值)和与max_weight成比例的大小。 最后,ax.autoscale_view()整齐地排列所有框并绘制 Hinton 图。
您应该获得如下输出:
等高线图
等高线图通常用于显示误差如何随机器学习算法(例如线性回归)中优化的系数的变化而变化。 如果线性回归系数为theta0和theta1,并且预测值和实际值之间的误差为Loss,则对于给定的Loss值,theta0和theta1的所有值 ]形成轮廓。 对于Loss的不同值,通过更改和theta1的值形成不同的轮廓。
准备
Loss,theta0,theta1和theta的数据(theta0和theta1具有最低误差)来自绘制轮廓图的回归问题之一。 如果theta0和theta1是大小为1 x n的向量,则Loss将为n x n矩阵形式。
导入所需的库。 我们将从 Matplotlib 引入另一个用于颜色映射的库:
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from matplotlib import cm
我们还需要了解网格的概念,因为等高线,曲面和流图也使用此概念:
- 网格是在几何空间中从两个向量派生的网格。 向量中的每个数据项均充当坐标,并且来自两个向量的坐标组合形成 2D 几何空间中的点。 这些向量坐标的所有可能组合所散布的区域以网格形式定义,例如:
x = [-3.0, 0., 3.0]和y = [-2.0, 2.0]。 向量x具有三个数据点,向量y具有两个数据点。 因此,我们在 2D 几何空间中总共有六个点(3 * 2),而这六个点是(-3.0, -2),(-3.0, 2.0),(0, -2.0),(0, 2.0),(3.0, -2.0)和(3.0, 2.0)。 现在,这六个点和 12 个数据项(6 * 2)再次表示为两个矩阵x和y,其中适用以下条件:X = [[-3.0, 0., 3.0], [-3.0, 0., 3.0]],一个2 x 3矩阵(行数等于Y的长度),Y = [[-2.0, 2.0], [-2.0, 2.0], [-2.0, 2.0]],3 x 2矩阵(行数等于X的长度)。 NumPy 具有函数np.meshgrid(x, y),用于使用x和y向量创建这些X和Y矩阵。 这就是我们将用于所有需求的东西。
操作步骤
以下是在给定回归问题中绘制损失函数的等高线图的代码:
- 从保存的文件中读取
Loss,theta0和theta1值:
Loss = pd.read_excel('Loss.xlsx')
theta0_vals = pd.read_excel('theta0.xlsx')
theta1_vals = pd.read_excel('theta1.xlsx')
- 指定图形大小:
fig = plt.figure(figsize=(12,8))
- 为
X和Y坐标创建网格:
X, Y = np.meshgrid(theta0_vals, theta1_vals)
- 绘制等高线图,并用相应的损耗值标记等高线:
CS = plt.contour(X, Y, Loss, np.logspace(-2,3,20), cmap=cm.coolwarm)
plt.clabel(CS, inline=1, fontsize=10)
- 在屏幕上显示轮廓图:
plt.show()
工作原理
这是代码的说明:
theta0 = np.linspace(-10, 10, 100)和theta1 = np.linspace(-1, 4, 100)帮助我们计算Loss,这是theta0和theta1值范围的误差。 所有这些数据都以 Excel 文件的形式提供,因此我们使用pd.read_excel()读取它们。np.meshgrid()在theta0和theta1之间创建网格,以获得X和Y,然后传递X,Y和Loss绘制轮廓图。CS = plt.contour()绘制轮廓图。np.logspace(-2,3,20)为Loss属性指定对数刻度的值范围,需要在等高线图中绘制。 在线性范围内,此范围为 0.01(10 的 -2 次方)到 1,000(10 的 3 次方)。20是它在此范围内绘制的样本数,使用它们绘制等高线。plt.clabel()指定将实际损耗值作为标签绘制在轮廓上。 从图中可以看出,损失(误差)的值从零一直到 545.559!
我们得到的输出如下:
更多
先前的屏幕截图仅代表theta0和theta1给定集合的Loss函数的各种轮廓。 我们还可以在同一图上绘制theta0和theta1的最佳值,以表示最小损失:
## Plot the minimum point(Theta at Minimum cost)
plt.plot(theta[0], theta[1], 'rx', markersize=15, linewidth=2)
plt.show()
这是绘图的样子。 红叉位置描绘了最佳theta,该最优theta为该回归问题提供了最低的误差:
三角剖分
三角剖分用于绘制地理地图,这有助于理解各个点之间的相对距离。 经度和纬度值用作 x,y 坐标来绘制点。 要绘制三角形,需要三个点。 用图中点的相应索引指定这些值。 对于给定的一组坐标,Matplotlib 可以自动计算三角形并绘制图形,或者可选地,我们也可以提供三角形作为参数。
准备
导入所需的库。 我们将介绍用于三角剖分的tri包:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.tri as tri
操作步骤
以下代码块生成 50 个随机点,自动创建三角形,然后绘制三角剖视图:
data = np.random.rand(50, 2)
triangles = tri.Triangulation(data[:,0], data[:,1])
plt.triplot(triangles)
plt.show()
工作原理
我们首先使用np.random.rand function生成50随机点,它会生成0和1之间的数字。tri.Triangulation()函数自动创建三角形,而plt.triplot()绘制三角剖分图。
这是输出图的外观:
更多
在上一个图中,我们自动生成了三角形。 在这里,我们将学习如何手动添加三角形:
- 以弧度为单位设置经度和纬度数据:
xy = np.array([[-0.101, 0.872], [-0.080, 0.883], [-0.069, 0.888],
[-0.054, 0.890], [-0.045, 0.897], [-0.057, 0.895],
[-0.073, 0.900], [-0.087, 0.898],
[-0.090, 0.904], [-0.069, 0.907]])
- 将
xy从弧度转换为度:
x = np.degrees(xy[:, 0])
y = np.degrees(xy[:, 1])
- 从
xy坐标中选择要转换为角度的三角形:
triangles = np.array([[1, 2, 3], [3, 4, 5], [4, 5, 6], [2, 5, 6],
[6, 7, 8], [6, 8, 9], [0, 1, 7]])
- 绘制三角剖分图:
plt.triplot(x, y, triangles, 'go-', lw=1.0)
- 绘制标签和标题:
plt.title('triplot of user-specified triangulation')
plt.xlabel('Longitude (degrees)')
plt.ylabel('Latitude (degrees)')
- 在屏幕上显示图:
plt.show()
下面是它的工作原理:
xy是弧度的坐标数组。np.degrees()将弧度转换为度;x和y以弧度表示,然后转换为度,其中x和y分别代表经度和纬度值。
三角形是要绘制的每个三角形的三点元组的数组。 数字是x和y中点的索引(0 至 9,共 10 点)。 输出如下:
流图
流图也称为流线图,用于可视化向量场。 它们主要用于工程和科学界。 他们使用向量及其速度作为基础向量的函数来绘制这些图。
准备
导入所需的库:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
操作步骤
以下代码块创建一个流图:
- 准备流图的数据:
x, y = np.linspace(-3,3,100), np.linspace(-2,4,50)
- 创建网格:
X, Y = np.meshgrid(x, y)
- 计算速度
U和V分别是X和Y的函数:
U = 1 - X**2
V = 1 + Y**2
- 绘制流图:
plt.streamplot(X, Y, U, V)
- 设置绘图的标题:
plt.title('Basic Streamplot')
- 在屏幕上显示图形:
plt.show()
工作原理
np.linspace(-3, 3, 100)在-3 到 3 的范围内创建 100 个数据点,并且连续点之间的间隔相等。x和y是长度为100和50的随机生成的向量,分别为 -3 至 3 和 -2 至 4。np.meshgrid(x, y)按照本章前面的说明创建网格。U和V是作为x和y的函数的速度向量。 流图是向量x,y和速度U和V的组合。plt.streamplot(X, Y, U, V)绘制流图,如下所示:
更多
在上一节中,我们已经看到了基本的流图。 我们可以根据流线的,速度和颜色来控制密度和厚度。 以下是代码及其输出:
## Define the speed as a function of U and V
speed = np.sqrt (U*U + V*V)
## Varying line width along a streamline
lw = 5 * speed / speed.max()
strm = plt.streamplot(X, Y, U, V, density=[0.5, 1], color=V,
linewidth=lw)
plt.colorbar(strm.lines)
plt.title('Varying Density, Color and Line Width')
plt.show()
np.sqrt(U*U + V*V)定义速度; 线宽(lw)定义为速度的函数。plt.streamplot()使用提供的参数绘制流图。density=[0.5, 1]指定要使用的密度值,color=V指定应基于V的值改变流线的颜色,linewidth指定应如何改变流线的宽度:
路径
Path是 Matplotlib 提供的一种用于绘制自定义图表的方法。 它使用 Matplotlib 提供的助手函数补丁。 让我们看看如何将其用于绘制简单图。
准备
导入所需的库。 这里将介绍两个新的包Path和patches:
import matplotlib.pyplot as plt
from matplotlib.path import Path
import matplotlib.patches as patches
操作步骤
以下代码块定义了点以及相关的直线和曲线,以形成整体图:
- 定义第一条曲线的点
verts1 = [(-1.5, 0.), # left, bottom
(0., 1.), # left, top
(1.5, 0.), # right, top
(0., -1.0), # right, bottom
(-1.5, 0.)] # ignored
- 绘制连接步骤 1 中定义的点的图形:
codes1 = [Path.MOVETO, # Go to first point specified in vert1
Path.LINETO, # Draw a line from first point to second
point
Path.LINETO, # Draw another line from current point to
next point
Path.LINETO, # Draw another line from current point to
next point
Path.CLOSEPOLY] # Close the loop
- 使用步骤 1 和步骤 2 中定义的点和线/曲线创建完整路径:
path1 = Path(verts1, codes1)
- 对第二个曲线重复相同的操作:
verts2 = [(-1.5, 0.), # left, bottom
(0., 2.5), # left, top
(1.5, 0.), # right, top
(0., -2.5), # right, bottom
(-1.5, 0.)] # ignored
codes2 = [Path.MOVETO, # Move to the first point
Path.CURVE3, # Curve from first point along the control
point and terminate on end point
Path.CURVE3, # Curve from current point along the control
point and terminate on end point
Path.CURVE3,
Path.CURVE3] # close by the curved loop
path2 = Path(verts2, codes2)
- 定义图形和轴域:
fig = plt.figure()
ax = fig.add_subplot(111)
- 创建第一个补丁并将其添加到轴域中:
patch1 = patches.PathPatch(path1, lw=4, zorder=2)
ax.add_patch(patch1)
- 创建第二个补丁并将其添加到轴域:
patch2 = patches.PathPatch(path2, facecolor='orange', lw=2,
zorder=1)
ax.add_patch(patch2)
- 设置
x和y轴的限制:
ax.set_xlim(-2,2)
ax.set_ylim(-2,2)
- 在屏幕上显示图:
plt.show()
工作原理
verts1和verts2定义了必须沿其绘制曲线的点。path1和path2定义了要绘制的每条曲线的完整路径。Path.MOVETO使曲线的起点到达verts中指定的第一点。Path.LINETO从当前位置的到指定的下一个点画一条线。Path.CLOSEPOLY关闭多项式曲线循环。Path.CURVE3沿着控制点从给定点绘制一条曲线,然后在第三点处终止。Path.CURVE4(在此示例中未使用)进行相同的操作,但是在两个控制点而不是一个。patches.PathPatch是一个辅助函数,可沿给定路径绘制曲线。zorder参数会覆盖绘制不同补丁的默认顺序。 在这种情况下,我们希望先绘制第二个补丁,然后再绘制第一个补丁,以便两个都可见。 否则,较小的补丁将隐藏在较大的补丁之后。lw指定线宽,facecolor指定要填充在色块内部的颜色,覆盖默认颜色。
这是代码的输出:
三、绘制多个图表和子图
在本章中,我们将介绍以下秘籍:
- 在同一轴域上绘制多个图形
- 在同一图中绘制子图
- 在一个会话中绘制多个图形
- 使用对数刻度
- 使用度量单位
介绍
在上一章中,我们了解了如何分别绘制各种图形。 在本章中,我们将学习如何在同一坐标轴域上绘制多个图形,在同一图形中绘制多个坐标轴/曲线以及在一个会话中绘制多个图形。 我们还将学习如何使用对数刻度和度量单位,例如厘米,英寸等。
在同一轴域上绘制多个图形
正如我们从第一章中学到的,轴域是绘制图形的空间,通常在图中看到的所有元素都是轴域的一部分。 我们在一幅图中可以有多个轴域。 在本秘籍中,我们将学习如何在同一轴域上绘制多个图表。
准备
我们将使用一个受试者工作特性(ROC)曲线的示例,通过它可以使用多个机器学习(ML)算法来比较给定的分类问题,并且针对该问题选择了表现最佳的算法。 ROC 曲线用真阳性率(TPR)以及假阳性率(FPR)的阈值概率范围绘制。 目的是随着和阈值概率的变化,看到 TPR 和 FPR 的敏感性。覆盖最大 ROC 曲线下面积(AUC)的算法是在分类准确性方面表现最佳的算法。
我们将 TPR 和 FPR 数据用于一组算法, k 最近邻算法(k-NN),多层感知器 MLP),随机梯度下降(SGD),随机森林(RF)和决策树(DT)在分类问题上运行以绘制图形。 该数据集作为本书代码库的一部分提供。
导入所需的库:
import matplotlib.pyplot as plt
import pandas as pd
操作步骤
这是在同一轴域上绘制多个 ROC 曲线的代码块:
- 使用
pandas从各自的 Excel 表中读取各种算法的 FPR 和 TPR 数据:
## K-nearest neighbor (KNN)
fpr_KNN = pd.read_excel('ROC_Curves.xlsx', 'fpr_KNN')
tpr_KNN = pd.read_excel('ROC_Curves.xlsx', 'tpr_KNN')
## Multilayer Perceptron(MLP)
fpr_MLP = pd.read_excel('ROC_Curves.xlsx', 'fpr_MLP')
tpr_MLP = pd.read_excel('ROC_Curves.xlsx', 'tpr_MLP')
## Stochastic Gradient Descent (SGD)
fpr_SGD = pd.read_excel('ROC_Curves.xlsx', 'fpr_SGD')
tpr_SGD = pd.read_excel('ROC_Curves.xlsx', 'tpr_SGD')
## Random Forest (RF)
fpr_RF = pd.read_excel('ROC_Curves.xlsx', 'fpr_RF')
tpr_RF = pd.read_excel('ROC_Curves.xlsx', 'tpr_RF')
## Decision Trees (DT)
fpr_DT = pd.read_excel('ROC_Curves.xlsx', 'fpr_DT')
tpr_DT = pd.read_excel('ROC_Curves.xlsx', 'tpr_DT')
- 绘制线形图,包括黑色阈值线,使用
fpr和tpr数据,在上一步中读取五种算法的每一种:
plt.plot([0, 1], [0, 1], 'k--')
plt.plot(fpr_KNN, tpr_KNN, label='KNN',color='green')
plt.plot(fpr_DT, tpr_DT, label='DecisionTree', color='orange')
plt.plot(fpr_RF, tpr_RF, label='Random Forest',color='purple')
plt.plot(fpr_MLP, tpr_MLP, label='MLP',color='red')
plt.plot(fpr_SGD, tpr_SGD, label='SGD', color='pink')
- 打印标签,标题和图例:
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC curve')
plt.legend(loc='best')
- 在屏幕上显示图:
plt.show()
工作原理
这是代码工作方式的说明:
pd.read_excel()语句读取五种算法(KNN,MLP,SGD,RF和DT)的 TPR 和 FPR 数据。plt.plot([0, 1], [0, 1], 'k--')以 45 度角绘制黑色虚线。 这是基本表现水平(参考线),与所有其他曲线相比,ROC 曲线在此线之上并覆盖其下最大面积的算法是被认为是表现最佳的算法 。- 随后的
plt.plot()语句绘制了五个选定算法中每个算法的 ROC 曲线。 每个绘图语句都在相同的轴域上绘制图形。 您可以在plt.show()之前绘制所需数量的图形,以在屏幕上显示图形。 - 参数标签和颜色在图形上区分了每种算法。 我们将在随后的章节中了解有关这些参数的更多信息。
plt.xlabel(),plt.ylabel()和plt.title()是绘图上的标签, 图例是这些图形标签放在图形上的位置。
您应该看到以下图:
从图中可以清楚地看出,SGD Classifier算法与所有其他算法相比效果不佳,因为该图表下的区域最低(或者最接近参考的参考) 虚线)。 对于该特定分类问题,MLP 算法是这五种算法中最好的,因为该曲线下的面积最高(或距参考块虚线最远)。
在同一图形上绘制子图
Matplotlib 提供了许多不同的方法和辅助函数,这些函数和辅助函数利用,axes方法在同一图形上绘制多个图并将它们布置为各种网格格式。 这使我们能够开发复杂的仪表板应用。
准备
对于本章中的示例,我们将使用与第 2 章“基本绘图入门”中介绍的相同的Wine Quality和Iris数据集。
图中的多个图排列在m x n网格中,其中m是行数,n是列数。 如果图中有六个绘图,我们可以将它们全部排成一排(每个都由 161、162、163、164、165 或 166 标识)或3 x 2(321、322,323、324、325 和 326)或2 x 3(231、232、233、234、235 和 236)或一列(611、612、613、614、615 和 616)。 前两位数字表示,行和列的数量的最后一位数字表示从 1 到 6 的连续数字(绘图总数),并从左向右,然后从上到下读取。
也可以将图指定为(3, 2, 1)而不是(321)。 当网格中有九个以上的绘图时,后一种表示法会造成混淆,而 Matplotlib 不接受它。 在这种情况下,如果您有一个(...),则必须使用(3, 4, 10),(3, 4, 11)或(3, 4, 12)而不是(3410),(3411)或(3412)。 3 x 4网格,共有 12 个绘图。
我们还可以绘制少于网格中允许的最大值的图,例如,在2 x 2网格中绘制 3 个图(其中是最大值)。
导入所需的库:
import pandas as pd
import matplotlib.pyplot as plt
操作步骤
以下代码块在一个图中绘制了三个图:
- 用三个轴域定义图形及其布局:
fig = plt.figure()
ax1 = plt.subplot(221)
ax2 = plt.subplot(222)
ax3 = plt.subplot(212)
- 在每个轴域上绘制折线图:
ax1.plot([1,2])
ax2.plot([2,1])
ax3.plot([2,4])
- 在屏幕上显示图:
plt.show()
工作原理
这是代码的说明:
plt.figure()为图形创建对象并为其分配空间。plt.subplot(221)在2 x 2网格中为第一个绘图创建轴域。plt.subplot(222)在2 x 2网格中为第二个图创建另一个轴域,该网格位于同一第一行中。plt.subplot(212)为第三个图又创建了一个轴域,但这是另一个2 x 1网格(212的前两位数字)的一部分,它是此2 x 1网格中的第二个图,因此放在第二行。由于第一个2 x 2网格未使用第二行,因此该网格将占据整个空间。
我们得到的输出如下:
如果我们为第三个图编码了plt.subplot(211),它将覆盖前两个图,因为 211 表示2 x 1网格中的第一个图,它将从第一行开始! 如果我们要绘制相同的三个图,但在第一列中排列两个,在第二列中排列一个,而不是第一行中当前的前两个图和第二行中的第三个图,那么我们将不得不指定绘图顺序为 221、223 和 122。 试试看作为练习!
更多
由于存在许多此类可能的网格,因此我们将再看到一个示例,该示例在2 x 2网格中包含四个不同的图,每个图具有不同类型的图形,直方图,折线图,散点图和条形图。 在最后一个示例中,我们一直使用和plt.subplot()方法一个接一个地添加轴域。 在此示例中,我们将一次定义网格中的所有轴域,然后使用索引来访问每个轴域并绘制不同的图形:
- 从
.csv文件中读取Wine Quality和Iris数据集,并为计算每个属性的均值和标准差:
wine_quality = pd.read_csv('winequality.csv', delimiter=';')
iris = pd.read_csv('iris_dataset.csv', delimiter=',')
iris_mean = iris.mean()
iris_std = iris.std()
- 这定义了图及其布局:
fig, axs = plt.subplots(2, 2, figsize=(8, 8))
- 在的第一个轴域上,将的直方图绘制为,的
alcohol属性,Wine Quality数据集。
axs[0, 0].hist(wine_quality['alcohol'])
axs[0, 0].set_title('Histogram')
axs[0, 0].set_xlabel('Alcohol Bins')
axs[0, 0].set_ylabel('Frequency')
- 在的第二个轴域上绘制
sepal_length和sepal_width的线形图:
axs[0, 1].plot(iris['sepal_length'], iris['sepal_width'])
axs[0, 1].set(title='Line', xlabel='Sepal Length', ylabel='Sepal
Width')
- 使用
petal_length和petal_width属性在第三轴域上绘制散点图:
axs[1, 0].scatter(iris['petal_length'], iris['petal_width'])
axs[1, 0].set(title='Scatter', xlabel='Petal Length', ylabel='Petal
Width')
- 在第四轴域上绘制条形图:
axs[1, 1].bar(['sepal_l','sepal_w', 'petal_l', 'petal_w'],
iris_mean, yerr=iris_std)
axs[1, 1].set(title='Bar', xlabel='Category', ylabel='Category
Mean')
- 设置整个图的标题:
plt.suptitle('Subplots Demo')
- 调整绘图之间的空间:
plt.tight_layout(pad=3, w_pad=1.0, h_pad=1.0)
- 在屏幕上显示图:
plt.show()
这是代码工作方式的说明:
iris.mean()和iris.std()计算Iris数据集中所有四个属性的均值和标准差。 这些将用于在该图的第四轴域上绘制条形图。fig, axs = plt.subplots(2, 2, figsize=(8, 8))定义2 x 2网格并将其分配给轴域列表,在每个轴域上绘制图形时,将使用相应的索引进行访问。axs[0, 0].hist(wine_quality['alcohol'])绘制和Wine Quality数据集中,酒精属性的直方图。axes[0,0]代表第一行第一列的第一个图,Python 索引从 0 开始。axs[0, 0].set_title('Histogram')设置第一个绘图的标题。axs[0, 0].set_xlabel('Alcohol Bins')设置 x 轴的标签,axs[0, 0].set_ylabel('Alcohol Bins')设置 y 轴的标签。axs[0, 1]代表第二个图的,位于第一行的中,第二列的上,在此轴域上绘制一条线形图。axs[0, 1].set()使用一个命令而不是三个单独的命令来设置标题,xlabel和ylabel。axs[1, 0]代表第三个图,放置在第二个行中,放置在第一个行中,并在此轴域上绘制了一个散点图。- 最后,
axs[1, 1]代表的第四个图,放置在的第二个行,的第二个列,并在此轴域上绘制条形图。yerr属性代表条形图代表的组的标准差,并在每个条形图上方显示为黑色垂直线。 线的长度是相对于条上所有其他线的长度; 线越长,该组(或条形图)的标准差越高。 plt.suptitle('Subplots Demo')设置图形的标题(所有四个图形的组合在一起)。plt.tight_layout(pad=3, w_pad=1.0, h_pad=1.0)确保四个图上的标签不相互重叠。pad参数控制图顶部的空间; 数字越大,图形标题与的标头和标头之间的空隙就越大,在其下方的两个图上。w_pad控制一行中两个图之间的间隔,h_pad控制一列中两个图之间的间隔。
您应该看到输出图,如下图所示:
在这种基于索引的轴域方法中,所有图都将具有相同的大小,因此我们无法像在本秘籍开始时在示例中所做的那样来管理不同大小的图。
在一个会话中绘制多个图形
到目前为止,我们已经学习了如何在单个轴域和一个图形中的多个轴域上绘制多个图。 在本秘籍中,我们将学习如何在给定的会话中绘制多个图形。
准备
在此示例中,我们还将使用相同的Iris数据集。 我们将绘制两个图形,并在每个图形中绘制多个图形。 在第一个图中,我们将使用另一种方法来创建具有不同大小图的网格。
导入所需的库:
import matplotlib.pyplot as plt
import pandas as pd
操作步骤
以下代码块绘制了两个图形,每个图形中都有多个图形:
- 从 Excel 读取
Iris数据:
iris = pd.read_csv('iris_dataset.csv', delimiter=',')
- 清除画布以开始一个新图:
plt.close('all')
- 使用相关的布局定义图 1 和子图:
fig = plt.figure(1, figsize=(12, 9))
ax1 = plt.subplot2grid((3, 3), (0, 0))
ax2 = plt.subplot2grid((3, 3), (0, 1), colspan=2)
ax3 = plt.subplot2grid((3, 3), (1, 0), colspan=2, rowspan=2)
ax4 = plt.subplot2grid((3, 3), (1, 2), rowspan=2)
- 在步骤 3 中定义的四个轴域上的每个轴域上绘制图形:
ax1.hist(iris['petal_width'])
ax2.scatter(iris['petal_length'], iris['petal_width'], s=50*iris['petal_length']*iris['petal_width'], alpha=0.3)
ax3.scatter(iris['sepal_length'], iris['sepal_width'])
ax4.violinplot(iris['petal_length'])
- 设置标题并调整绘图之间的间隔:
plt.suptitle('Figure 1: Grid Plotting Demo', fontsize=20)
plt.tight_layout(pad=5, w_pad=0.5, h_pad=1.0)
- 定义图 2 及其大小:
plt.figure(2, figsize=(12, 5))
- 设置条形图的数据:
names = ['group_a', 'group_b', 'group_c', 'group_d', 'group_e']
values = [1, 10, 50, 100, 500]
- 定义第一轴域并绘制条形图:
plt.subplot(131)
plt.bar(names, values, color='orange')
- 定义第二轴域并绘制散点图:
plt.subplot(132)
plt.scatter(names, values, color='orange')
- 定义第三轴域和一个折线图:
plt.subplot(133)
plt.plot(names, values, color='orange')
- 设置整体图形的标题,并调整图形中各图之间的空间:
plt.suptitle('Figure 2: Row Plotting Demo', fontsize=20)
plt.tight_layout(pad=5, w_pad=0.5, h_pad=1.0)
- 在屏幕上显示该图:
plt.show()
工作原理
这是代码的说明:
plt.close('all')在开始新图形之前清除空间。fig = plt.figure(1, figsize=(12, 9))定义了图 1 ,其大小等于(12, 9)。ax1 = plt.subplot2grid((3, 3), (0, 0))创建ax1轴域,将在其中绘制第一个图,ax1是9个轴域的3 x 3网格中的第一个轴域。 Python 索引从 0、1 和 2 开始,分别代表第一,第二和第三行或列。ax2 = plt.subplot2grid((3, 3), (0, 1), colspan=2)创建ax2轴域,该轴域跨越3 x 3网格的两列,从第一个行和第二个列开始。ax3 = plt.subplot2grid((3, 3), (1, 0), colspan=2, rowspan=2)创建一个ax3轴域,该轴域跨越两列和两行,从第二行和第一列开始。ax4 = plt.subplot2grid((3, 3), (1, 2), rowspan=2)创建一个ax4轴域,该轴域跨越两行一列,从第二行行和第三列开始。- 与上一个秘籍一样,我们现在分别在四个轴域上分别绘制直方图,气泡图,散点图和提琴图。
plt.suptitle('Figure 1: Grid Plotting Demo', fontsize=20)设置图 1 的标题,字体大小为20。plt.tight_layout(pad=5, w_pad=0.5, h_pad=1.0)调整图之间的间隔,以使标签不重叠。plt.figure(2, figsize=(12, 5))以(12, 5)的大小开始第二个图形。- 名称和值是要绘制在三个图上的, x ,和 y 轴上要绘制的数据的 Python 列表。
- 与前面的示例一样,我们在
1 x 3的网格中绘制三个图,并绘制一个条形图,一个散布图和一个线形图。 然后,我们为图形设置标题,并调整图之间的空间,以使其没有重叠,就像其他子图一样。
您应该看到如下所示的输出数字:
更多
Matplotlib 还提供了另一个名为AxesGrid的工具包,它涵盖了更高级的网格选项,包括网格中的图像。 我们将在第 13 章“使用axis_grid1工具包”中进行介绍。
对数刻度
当数据的范围从很小的值到很大的值时,按线性比例绘制它可能无法使正确理解和数据点的相对大小。 在这种情况下,将使用对数刻度。
准备
对于此示例,我们将使用一些虚拟数据来演示线性刻度和对数刻度之间的差异。
导入所需的库:
import matplotlib.pyplot as plt
操作步骤
以下代码块绘制了三个图形,一个以线性刻度绘制,和其他两个以对数刻度绘制。 两个对数图还演示了如何调整物理大小和数据规模:
- 定义图及其布局:
fig, (ax1, ax2, ax3) = plt.subplots(1, 3)
- 在轴域
ax1上以线性比例绘制折线图:
ax1.plot([0.1, 5, 10, 500], [0.01, 25, 100, 10000], "x-")
ax1.set(title="Linear Scale", xlim=(1e1, 1e3), ylim=(1e2, 1e4))
- 在 x 和 y 轴域上绘制一个具有对数刻度的空图:
ax2.set(title="adjustable = box", xscale="log", yscale="log", xlim=
(1e1, 1e3), ylim=(1e2, 1e3), aspect=2)
- 在
ax3, x 和 y 轴上以对数刻度在ax3上绘制线形图:
ax3.plot([0.1, 5, 10, 500], [0.01, 25, 100, 10000], "o-")
ax3.set(title="adjustable = datalim", xscale="log", yscale="log",
adjustable="datalim", xlim=(1e-1, 1e3),
ylim=(1e-2, 1e4), aspect=1)
- 调整绘图之间的空间,并在屏幕上显示图形:
plt.tight_layout()
plt.show()
工作原理
这是代码的说明:
fig和(ax1, ax2, ax3) = plt.subplots(1, 3)定义图形的布局,其中三个坐标轴对象将被绘制成一行。- 在
ax1轴域上绘制了一个简单的折线图,其中设置了, x 和 y 轴限制。 由于数据范围非常大,因此并非所有点都清晰可见,并且之间的相对间隙不容易可视化。 - 在
ax2上,显示了对数刻度,其中没有任何图表。ax2.set()设置绘图的所有参数。xscale="log"和yscale="log"将 x 和 y 轴设置为对数刻度。aspect=2将 y 刻度数据设置为 x 刻度数据的大小的两倍。 如您所见, y 轴上 10^2 到 10^3 之间的距离是 x 轴上距离的两倍。 - 在
ax3上,此处绘制了对数刻度和在ax1上绘制的相同折线图,以显示差异。 在这里,我们可以清楚地看到所有四个点,还可以看到它们之间的相对距离。adjustable="datalim"调整/扩展 x 或 y 限制,以适应指定的长宽比。 的第二个图(ax2)中省略了此属性,因此的默认参数box会调整物理对象大小(而不是数据规模)来适应宽高比。
您应该看到如下输出图:
更多
让我们再举一个关于如何使用对数刻度的示例。 假设在组织中,员工根据其职位分为五类。 这五个类别中的每一个都进一步分为男人和女人。 对于这 10 个类别中的每个类别(5 名男性和 5 名女性),我们都有平均薪水和标准差。 绘制此数据以查看薪水数据如何在男女群体之间分配。
以下是代码及其工作方式:
- 导入所需的库:
import matplotlib.pyplot as plt
import numpy as np
- 定义包含男性和女性均值和标准差数据的 Python 列表:
menMeans = [3, 10, 100, 500, 50]
menStd = [0.75, 2.5, 25, 125, 12.5]
womenMeans = [1000, 3, 30, 800, 1]
womenStd = [500, 0.75, 8, 200, 0.25]
- 定义图形布局,
ind列表,其中menMeans条将放置在 x 轴,每个条形的width,然后以红色绘制men数据的条形图,并在其顶部显示黑线,指示该组的标准差的大小:
fig, ax = plt.subplots()
ind = np.arange(len(menMeans))
width = 0.35
p1 = ax.bar(ind, menMeans, width, color='lightblue', bottom=0,
yerr=menStd)
- 同样,以黄色绘制
womenMeans条形图,与menMeans条形相邻,然后设置标题、xticks的位置及其 x 轴标签:
p2 = ax.bar(ind + width, womenMeans, width, color='orange',
bottom=0, yerr=womenStd)
ax.set_title('Scores by category and gender')
ax.set_xticks(ind + width / 2)
ax.set_xticklabels(('C1', 'C2', 'C3', 'C4', 'C5'))
- 最后,
ax.set_yscale('log')将 y 轴刻度设置为对数,ax.legend((p1[0], p2[0]), ('Men', 'Women'))设置图例。 然后,plt.show()在屏幕上显示绘图。
这是输出条形图的外观:
Matplotlib supports four different scales. The default is linear, and we have covered log in this recipe. You can refer to the Matplotlib documentation for the other two scales: symlog and logit.
使用度量单位
有时,我们可能具有使用一个度量单位的数据,但是想要使用不同的度量单位来绘制图,或者有时我们可能想要对, x 和 y 轴使用不同的度量单位,例如 x 轴为厘米,y 轴为英寸。 当我们绘制角度时,度数和弧度也是如此。 Matplotlib 没有内置这些功能,但是 GitHub 上有一个扩展工具basic_units.py,可启用这些不同的度量单位。 该 Python 模块当前仅支持厘米/英寸和弧度/度。 对于其他度量单位,例如千克/磅,千米/海里等,我们将必须更新此工具模块。
basic_units.py is not a standard package to be installed like all other Python packages. It is a user-defined Python program that needs to be copied into your working directory. Then, in the main program, import the functions from this program similar to the way we import any other package or user-defined programs.
准备
将basic_units.py复制到工作目录后,即可开始使用那里的所有可用功能。
导入所需的库。 在这里,我们将介绍 Matplotlib 的另外两个函数lines,它具有用于绘制线条的对象和text,用于在图表上标注对象:
import matplotlib.lines as lines
import matplotlib.text as text
from basic_units import cm, inch
import matplotlib.pyplot as plt
操作步骤
以下代码块绘制了两个图,一个是厘米,另一个是英寸,以演示两个度量单位之间的差异:
- 定义一个具有两个连续图的图形:
fig, ax = plt.subplots(1,2)
- 定义
line和要添加到第一个轴域的text艺术家:
line = lines.Line2D([0*cm, 1.5*cm], [0*cm, 2.5*cm], lw=2,
color='black', axes=ax[0])
t = text.Text(3*cm, 2.5*cm, 'text label', ha='left', va='bottom',
axes=ax[0])
- 将艺术家添加到轴域
0,并设置限制,度量单位和网格:
ax[0].add_line(line)
ax[0].add_artist(t)
ax[0].set_xlim(-1*cm, 10*cm)
ax[0].set_ylim(-1*cm, 10*cm)
ax[0].xaxis.set_units(cm)
ax[0].yaxis.set_units(cm)
ax[0].grid(True)
- 定义要添加到第二轴域的
line和text艺术家:
line = lines.Line2D([0*cm, 1.5*cm], [0*cm, 2.5*cm], lw=2,
color='black', axes=ax[1])
t = text.Text(3*cm, 2.5*cm, 'text label', ha='left', va='bottom',
axes=ax[1])
- 将艺术家添加到坐标轴
1并设置限制,度量单位和网格:
ax[1].add_artist(line)
ax[1].add_artist(t)
ax[1].set_xlim(-1*cm, 10*cm)
ax[1].set_ylim(-1*cm, 10*cm)
ax[1].xaxis.set_units(inch)
ax[1].yaxis.set_units(inch)
ax[1].grid(True)
- 设置图的标题并调整图之间的间距:
plt.suptitle("Demonstration of Units Of Measurement")
plt.tight_layout(pad=3)
- 在屏幕上显示该图:
plt.show()
工作原理
这是代码工作方式的说明:
fig, ax = plt.subplots(1,2)使用同一行上的两个轴域对象定义图形。 由于只有两行的一行,因此ax是一维向量,因此我们将使用ax[0]和ax[1]进行访问。line = lines.Line2D([0*cm, 1.5*cm], [0*cm, 2.5*cm], lw=2, color='black', axes=ax[0])在轴域ax[0]上绘制黑线段,并以lw=2绘制输入数据,单位为厘米。- 类似地,
t = text.Text(3*cm, 2.5*cm, 'text label', ha='left', va='bottom', axes=ax[0])将ax[0]的ax[0]定义为指定位置(3, 2.5)的ax[0]对象,以厘米为单位,左侧对齐为水平,底部对齐为垂直。
It should be noted that Matplotlib does not support sharing objects across different axes; we need to explicitly specify for each object in which axes it is to be included. We specified axes=ax[0] for the line plot, since the same line is plotted again on ax[1], and we had to tell Matplotlib on which axis it is plotting the line at any given time. This also means that if the same line or text is to be drawn on two different axis, then it will have to be repeated twice.
ax[0].add_line(line)和ax[0].add_artist(t)在ax[0]上添加行和文本对象。 记住,艺术家是一个实际在画布/图表上绘制对象的对象。 实际上,add_line也可以用add_artist代替,就像我们稍后对ax[1]所做的那样。ax[0].xaxis.set_units(cm)和ax[0].yaxis.set_units(cm)设置 x 轴和 y 轴的测量单位,以进行实际显示。 对于ax[0],它设置为厘米,对于ax[1],它设置为英寸。 对于两个轴域,输入数据均以厘米为单位。ax[0].grid(True)显示网格以及 x 和 y 轴上的主要刻度。 这有助于可视化图形上任何位置的精确坐标值。plt.suptitle()设置图形标题,plt.tight_layout(pad=3)调整图形之间的间距,pad=3确保图形标题足够在图形之前。- 对
ax[1]重复完全相同的步骤,唯一的区别是ax[1].xaxis.set_units(inch)和ax[1].yaxis.set_units(inch)是用英寸而不是cm指定的。
该图的外观如下:
由于在两个图上的比例都是和相同,因此线条的大小以英寸为单位要比以厘米为单位要小。
更多
这是在 x 和 y 轴上使用厘米和英寸的混合的另一个示例。 我们有四个条形图,其中和相同的输入数据绘制在2 x 2的网格上。
导入所需的库:
import numpy as np
from basic_units import cm, inch
import matplotlib.pyplot as plt
下面的代码在2 x 2的网格中用四个条形图绘制图形:
- 定义数据和度量单位:
cms = cm * np.arange(0, 21, 3)
bottom = 0 * cm
width = 0.8 * cm
- 定义图及其布局:
fig, axs = plt.subplots(2, 2)
- 在第一轴域上绘制条形图,并以厘米为单位设置
xticks:
axs[0, 0].bar(cms, cms, bottom=bottom)
axs[0, 0].set_xticks(cm * np.arange(0, 21, 3))
- 在第二轴域上绘制条形图,其中, x 轴以厘米为单位, y 轴以英寸为单位:
axs[0, 1].bar(cms, cms, bottom=bottom, width=width, xunits=cm,
yunits=inch)
axs[0, 1].set_xticks(cm * np.arange(0, 21, 3))
- 在第三轴域上绘制条形图,其中, x 轴以英寸为单位, y 轴以厘米为单位:
axs[1, 0].bar(cms, cms, bottom=bottom, width=width, xunits=inch,
yunits=cm)
axs[1, 0].set_xticks(cm * np.arange(0, 21, 3))
axs[1, 0].set_xlim(2, 6)
- 以 x 和 y 轴为单位在第四轴域上绘制条形图,以英寸为单位:
axs[1, 1].bar(cms, cms, bottom=bottom, width=width, xunits=inch,
yunits=inch)
axs[1, 1].set_xticks(cm * np.arange(0, 21, 3))
axs[1, 1].set_xlim(2 * cm, 6 * cm)
- 调整绘图之间的间距,并在屏幕上显示图形:
fig.tight_layout()
plt.show()
以下是其工作原理的说明:
- 准备 x 和 y 坐标的输入数据,设置条形的底部偏移量和条形的宽度。
fig, axs = plt.subplots(2, 2)在2 x 2网格中定义图形布局。axs[0, 0].bar(cms, cms, bottom=bottom)在axs[0, 0]和上绘制条形图,输入数据以厘米为单位。axs[0, 0].set_xticks(cm * np.arange(0, 21, 3))在 x 轴上设置刻度线,以使其与条形对齐。axs[0, 1]上的条形图与axs[0, 0]完全相同,除了轴域的单位从厘米变为英寸,这是在绘图上可见的。axs[1, 0]上的条形图再次类似于axs[0, 0]上的条形图,但 x 轴上的单位更改为英寸,而axs[1, 0].set_xlim(2, 6)将 x 轴限制设置为(2,6)。 在这里,仅使用标量来设置限制值,没有任何测量单位,这意味着无论 x 轴测量单位是什么,限制值都适用,在这种情况下,范围为两到六英寸。axs[1,1]上的条形图使用英寸作为, x 和 y 轴的度量单位,并设置 x 轴限制(2 到 6 厘米),将 x 轴的度量单位转换为英寸。 因此它将转换为英寸,在这种情况下将转换为 0.79 到 2.362 英寸。
您应该看到如下图:
四、开发可视化来提高发布质量
在本章中,我们将介绍以下秘籍:
- 颜色,线条样式和标记自定义
- 使用标准颜色表
- 用户定义的颜色和颜色表
- 处理图例
- 自定义标签和标题
- 使用自动缩放和轴限制
- 自定义刻度和刻度标签
- 自定义轴线
- 双生轴域
- 使用图案填充
- 使用标注
- 使用样式表
介绍
Matplotlib 提供了许多功能来自定义图形的所有属性。 它还提供了许多不同的方法来实现相同的功能,从而提供最大的灵活性和多种选择。 在本章中,我们将介绍每个图形属性可用的标准功能,例如颜色,标签,标题,图例,刻度线,轴线,样式,阴影和标注。 第 6 章和“带有高级功能的绘图”将介绍诸如属性循环,变换,GridSpec和路径效果之类的高级主题。
颜色,线条样式和标记自定义
Matplotlib 支持许多不同的方式来指定颜色,线条样式和标记。 在本秘籍中,我们将学习如何使用这些功能。
准备
导入以下必需的库:
import numpy as np
import matplotlib.pyplot as plt
操作步骤
下面的代码块绘制了五个不同的图,以演示用于指定颜色,线条样式和标记的大多数可能组合:
- 定义图形布局,如下所示:
fig = plt.figure(figsize=(12,6))
- 为每个图定义轴域名称:
ax1 = plt.subplot(321)
ax2 = plt.subplot(322)
ax3 = plt.subplot(323)
ax4 = plt.subplot(324)
ax5 = plt.subplot(325)
ax6 = plt.subplot(326)
- 设置
x坐标的数据:
x = np.linspace(0, 10, 20)
- 以下是许多颜色规格的演示:
xkcd:sky blue:xkcd颜色调查的名称green:CSS4 颜色名称1F1F1F1F:RGBA 格式的十六进制值; 数字范围为 0-F。b:CSS4 颜色的缩写1C0B2D:RGB 格式的十六进制值pink:色表C4:属性周期中的颜色; 这是区分大小写的,必须将C大写
我们用以下代码格式表示它们:
color_list = ['xkcd:sky blue', 'green', '#1F1F1F1F', 'b', '#1C0B2D',
'pink', 'C4']
for i, color in enumerate(color_list):
y = x - (-5*i + 15)
ax1.plot(x, y, color)
ax1.set_title('colors demo')
- 以下是许多线条样式的演示:
line_style = ['-', '--', '-.', ':', '.']
for i, ls in enumerate(line_style):
y = x - (-5*i + 15)
line, = ax2.plot(x, y, ls)
ax2.set_title('line style demo')
plt.setp(line, ls='steps')
- 这是许多标记规格的演示:
marker_list = ['.', ',', 'o', 'v', '^', 's', 'p', '*', 'h', 'H',
'D']
for i, marker in enumerate(marker_list):
y = x - (-5*i + 15)
ax3.plot(x, y, marker)
ax3.set_title('marker demo')
- 以下是指定颜色,线条样式和标记的组合的演示:
y = x # reset y to x
ax4.plot(x, y-10, 'k-d')
ax4.plot(x, y-5, 'c--')
ax4.plot(x, y, '|')
ax4.plot(x, y+5, '-.')
ax4.plot(x, y+10, color='purple', ls=':', marker='3')
ax4.plot(x, y+15, color='orange', linestyle=':', marker='1')
ax4.set_title('combination demo')
- 以下是指定线条和标记的颜色和大小的演示:
ax5.plot(x, y-10, 'y-D', linewidth=2, markersize=4,
markerfacecolor='red',
markeredgecolor='k',markeredgewidth=1)
ax5.plot(x, y-5, 'm-s', lw=4, ms=6, markerfacecolor='red',
markeredgecolor='y', markeredgewidth=1)
ax5.set_title('Line and Marker Sizes Demo')
- 以下是虚线端帽样式的演示:
dash_capstyles = ['butt','projecting','round']
for i, cs in enumerate(dash_capstyles):
y = x - (-5*i + 15)
ax6.plot(x, y, ls='--', lw=10, dash_capstyle=cs)
ax6.set_title('dash capstyle demo')
- 仅使用绘图之间的空间,然后在屏幕上显示图形:
plt.tight_layout()
plt.show()
工作原理
以下是代码的输出,后面是其工作原理的解释:
np.linspace(0, 10, 20)在 0 到 20 的范围内创建 20 个值,它们映射到 x 轴。fig = plt.figure(figsize=(12,6))定义大小为(12, 6)的图形,然后使用plt.subplot()定义六个子图。- 第一个图展示了可以在图中指定颜色的各种方法。
color_list是绘制线条图的颜色列表。for循环遵循列表中每种颜色的绘图线。for循环中的enumerate允许两个变量:一个用于从零开始的索引,另一个用于列表中的实际项目:xkcd:sky blue-这是xkcd颜色调查中的一种颜色。xkcd:必须在实际颜色代码之前。 请在此站点上找到颜色的完整列表。- 颜色代码(
b,g,r,c,m,y,k,w)及其扩展名(blue,green,red,cyan,magenta,yellow,black,white)。 - (
tab:blue,tab:orange,tab:green,tab:red,tab:purple,tab:brown,tab:pink,tab:gray,tab:olive,tab:cyan)是来自表格的颜色T10分类调色板(这也是默认的颜色周期)。 我们可以在它们之前使用tab:来指定这些颜色,也可以不使用tab来指定这些颜色。 两者都是可以接受的。 - 我们也可以指定 RGB 或 RGBA 格式的十六进制值。 任何通道的十六进制值范围从
00到FF。 因此,RBG 的范围从000000到FFFFFF,而 RGBA 的范围从00000000到FFFFFFFF。A代表 Alpha,代表颜色的透明度; 朝向00高度透明,朝向FF不透明。 - 所有这些都不区分大小写,因此我们可以使用大写或小写字母。
- 另外一个选项是
CN,其中C区分大小写,并且必须是大写字符,后跟数字,这是默认颜色周期中颜色的索引。 如上所述,默认周期中的第一种颜色是蓝色,然后是橙色,绿色,红色,紫色,等等。 因此,C0代表蓝色,C1代表orange,依此类推。
- 第二个图演示了六种可用的线型。 它们是破折号(
-),实线(--),破折号和点(-.),冒号(:),点(.)和实线(' ')。 最后一条实线用于演示属性设置函数plt.setp()的可用的steps样式。 此选项不能像其他线型一样直接使用。 - 第三幅图展示了各种标记。 并非所有可用的标记都在此处绘制。 有关标记的完整列表,请参阅此处的 Matplotlib 文档。
- 第四幅图演示了如何指定颜色,线条样式和标记及其缩写或全名的组合。 我们可以在字符串中指定所有三个参数,例如
g-^,也可以只指定其中一个或两个参数,例如g或--或D,在这种情况下,它对此处未指定的属性的其他参数使用默认值。 我们还可以单独指定颜色,例如,颜色为purple,线型为:,标记为>等。 - 图五演示了如何为标记的线宽,标记大小,边缘和面颜色指定大小和颜色参数。
- 最后,图六展示了虚线样式下的端帽样式。
使用标准颜色表
在上一秘籍中,我们看到了在绘制图形时如何使用颜色。 如果我们想用视觉感知的颜色可视化数据范围以了解数据中的图案,那么创建与所需范围内的数据变化匹配的颜色组合将很繁琐。 Matplotlib 提供了一系列预定义的颜色表,可以利用这些颜色表满足任何特定要求。 Matplotlib 还启用了用户定义的颜色表,这些颜色表将在下一个秘籍中介绍。
In Python notebooks, you can type matplotlib.pyplot.cm. and press Tab or type help (matplotlib.pyplot.cm) to get a complete list of the available colormaps.
准备
在此示例中,我们将使用熟悉的Iris数据集。 我们将首先创建一个相关矩阵,并应用标准的颜色表以查看其外观。 在第 2 章和“基本图入门”中,我们看到了相同的相关矩阵作为热图绘制。 在那里,我们使用了hot色彩表,但是我们没有涉及色彩表的细节。 我们将在这里解释。
导入以下必需的库:
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
操作步骤
以下代码块绘制了具有Blues颜色表的相关矩阵:
- 从 Excel 文件中读取
winequality数据:
wine_quality = pd.read_csv('winequality.csv', delimiter=';')
corr = wine_quality.corr()
- 定义图及其大小:
plt.figure(figsize=(12,8))
- 绘制相关图,关联的
x和y刻度以及色条:
plt.imshow(corr, cmap='Blues')
plt.colorbar()
plt.xticks(range(len(corr)),corr.columns, rotation=45)
plt.yticks(range(len(corr)),corr.columns)
- 在屏幕上显示该图:
plt.show()
工作原理
以下是其工作原理的说明:
pd.read_csv()读取winequality数据,wine_quality.corr()计算相关矩阵。plt.imshow(corr, cmap='Blues')将相关矩阵显示为图像并应用标准色表之一:Blues。plt.colorbar()显示颜色条,该颜色条指示哪个颜色份额代表哪个数据范围。plt.xticks()和plt.yticks()绘制代码(数据集中每个属性一个)和 x 和 y 轴的相应代码标签。plt.xticks()中的参数rotation=45表示报价标签应与相应轴成 45 度角放置。
您应该看到以下热图。 不出所料,数据范围为 -0.6 到 1.0(相关性只能在 -1.0 和 1.0 之间)。 1.0 一端用dark blue颜色表示,另一端用white颜色表示 -1,深蓝色和白色之间的深到浅阴影表示 1.0 和 -1.0 之间的数字:
更多
在上图中,我们显示了输入数据中可用的完整数据范围。 但是,我们可以使用plt.clim()方法限制要进行颜色编码的数据范围。 当存在异常值时(变量的一些条目与其余数据相比太大或太小),这很有用,然后默认情况下,颜色表会扩展整个数据范围的颜色代码。 当存在离群值时,由于范围较大,大多数值会变得模糊,并且离群值会以极端的颜色突出。 如果要抑制离群值的影响,可以限制不包含离群值的数据范围,并在颜色条中使用完整的颜色列表来绘制所需范围。 这给出了数据分布的真实情况。 这是我们可以完成此操作的方法。
首先,我们将噪声添加到已创建图像的图像像素的 10% 中。 我们将不得不做一些数据预处理以添加噪声,从而使数据范围超出 -1 到 1。然后,我们将绘制具有完整数据范围和 -1 到 1 的数据范围的同一图像 ,看看两者之间的区别。 可以看出,在第一张图像中,一些单元格(归因噪声或离群值)以蓝色或白色亮着,而所有其他单元格都模糊了,但是在第二张图像中,所有单元格颜色在 -1 到 1 的范围内均匀地有所不同:
- 在图像像素的 10% 中产生噪声:
np.random.seed(0)
mask = (np.random.random(corr.shape) < 0.1)
columns = corr.columns
corr1 = np.array(corr)
corr1[mask] = np.random.normal(0, 5, np.count_nonzero(mask))
corr = pd.DataFrame(corr1, columns=columns)
- 定义图及其大小:
plt.figure(figsize=(12, 5))
- 定义第一个轴域并在上面绘制相关图:
plt.subplot(121)
plt.imshow(corr, cmap='Blues')
plt.colorbar()
plt.xticks(range(len(corr)),corr.columns, rotation=75)
plt.yticks(range(len(corr)),corr.columns)
- 定义第二个轴域并绘制相关图,并限制数据:
plt.subplot(122)
plt.imshow(corr, cmap='Blues')
plt.colorbar(extend='both')
plt.clim(-1, 1)
plt.xticks(range(len(corr)),corr.columns, rotation=75)
plt.yticks(range(len(corr)),corr.columns)
- 调整绘图之间的空间,并在屏幕上显示图形:
plt.tight_layout()
plt.show()
这是代码及其工作方式的说明:
np.random.seed(0)设置种子,以便每次我们运行随机数生成器时,我们都会获得相同的数据。 当我们多次运行相同的代码时,这可以确保结果的可重复性。mask = (np.random.random(corr.shape) < 0.1)创建一个大小为corr的矩阵,所有小于 0.1 的值都以True作为条目; 否则为False。columns = corr.columns从corrPandas 数据帧中提取列名称,以供以后使用。corr1 = np.array(corr)为我们的corr数据帧创建了一个 NumPy 数组,因为下一条语句与 NumPy 数组(而不是数据帧)一起很好地工作。corr1[mask] = np.random.normal(0, 5, np.count_nonzero(mask))通过为 10% 的条目生成随机正态值来替换corr1中与掩码中的True条目相对应的条目,并且该分布的平均值为零,标准差为 5。 想法是用代表噪声的较大值替换 10% 的条目。corr = pd.DataFrame(corr1, columns=columns)为噪声估算的相关矩阵创建数据帧。plt.subplot(1, 2, 1)为第一个绘图创建轴域,我们将在其中显示噪声输入的图像。plt.imshow(corr, cmap='Blues')在plot1中绘制图像,后跟颜色条,刻度和刻度标签。plt.subplot(1, 2, 2)创建第二个绘图的轴域,在其中将数据范围限制在 -1 和 1 之间。lt.colorbar(extend='both')绘制带有两端箭头的颜色条,指示范围超出了显示范围。plt.clim(-1, 1)将颜色(实际上是数据范围)限制在 -1 和 1 之间。
您应该看到以下图:
用户定义的颜色和颜色表
在上一个秘籍中,我们学习了如何利用预定义的颜色和颜色表以及如何针对特定需求自定义它们。 在本秘籍中,我们将学习如何创建自己的颜色表。 在此示例中,我们将使用Iris数据集。
准备
我们将首先学习如何创建离散的颜色表,然后是连续的颜色表。
导入以下必需的库:
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from matplotlib.colors import LinearSegmentedColormap
操作步骤
以下代码块显示了三个图表; 第一个使用标准色表coolwarm,另外两个使用用户定义的离散色表。 在两个用户定义的颜色中,第一个使用纯红色(1, 0, 0),绿色(0, 1, 0)和蓝色(0, 0, 1),而另一个使用 RGB 的混合颜色(1, 0.5, 0),(0.25, 1, 0),(0, 0.5, 1)以生成三种离散颜色。 请注意,在第一个颜色表元组(1, 0, 0)中,只有红色是 1; 绿色和蓝色为零。 在第二个颜色中,第一个和第二个颜色是(1, 0.5, 0)和(0.25, 1, 0)表示它们是红色和绿色的组合,而第三个颜色是绿色和蓝色的组合。
我们在这里使用三种离散的颜色,因为我们在输入数据集中有三个聚类。 我们应该具有与簇数一样多的颜色:
- 从 Excel 读取
Iris数据并将文本类名称替换为数值:
iris = pd.read_csv('iris_dataset.csv', delimiter=',')
iris['species'] = iris['species'].map({"setosa" : 0, "versicolor" :
1, "virginica" : 2})
- 定义图及其布局:
fig, axs = plt.subplots(1,3, figsize=(9,6))
fig.subplots_adjust(left=0.0, bottom=0.05, right=0.9, top=0.95,
wspace=0.6)
- 定义一个函数来绘制图形:
def plot_graph(axes, cm, cbaxs):
im = axes.scatter(iris.petal_length, iris.petal_width,
s=10*iris.petal_length*iris.petal_width, c=iris.species,
cmap = cm)
caxs = plt.axes(cbaxs)
fig.colorbar(im, caxs, ticks=range(3), label='clusetr #')
- 使用从预定义的颜色表
coolwarm中选择的三种颜色绘制Iris数据集簇:
cbaxs = [0.24, 0.05, 0.03, 0.85] # left, bottom, width and height
plot_graph(axs[0], plt.cm.get_cmap('coolwarm', 3), cbaxs)
- 使用纯红色,绿色和蓝色的自定义颜色绘制
Iris数据群集:
colors = [(1, 0, 0), (0, 1, 0), (0, 0, 1)] # R -> G -> B
cm = LinearSegmentedColormap.from_list('custom_RGB_cmap', colors,
N=3)
cbaxs = [0.58, 0.05, 0.03, 0.85]
plot_graph(axs[1], cm, cbaxs)
- 使用自定义颜色混合颜色组合来绘制
Iris数据群集:
colors = [(1, 0.5, 0), (0.25, 0.5, 0.25), (0, 0.5, 1)] # R -> G -> B
cm = LinearSegmentedColormap.from_list('dummy', colors, N=3)
cbaxs = [0.95, 0.05, 0.03, 0.85]
plot_graph(axs[2], cm, cbaxs)
- 在屏幕上显示该图:
plt.show()
工作原理
以下是代码及其工作方式的说明:
fig, axs = plt.subplots(1,3, figsize=(9,6))定义具有连续三幅图的图形布局,图形大小为(9, 6)。fig.subplots_adjust(left=0.0, bottom=0.05, right=0.9, top=0.95, wspace=0.6)定义图形的边界框,在图形的左侧,底部,右侧和顶部定义的所有四个方向上都留有空间。wspace定义一行中各图之间要保留的空间量,以使它们的标签或图之间没有重叠。hspace是另一个参数,它控制列中各图之间的间隔。 在本示例中,我们没有使用它,因为我们仅将所有图形绘制在一行中。plot_graph()是用户定义的函数,用于绘制具有给定参数,轴域,颜色表和颜色条轴域的图形。axs.scatter()使用给定的参数绘制散点图。caxs = plt.axes(cbaxs)在给定的坐标轴上定义颜色条。fig.colorbar()为具有定义颜色的每个群集绘制带有三个刻度的色条,并使用cluster #标记色条。- 我们将第一个图形绘制在
axes[0]上,预定义的颜色表coolwarm的前三个颜色和色条轴域cbaxs =[0.24, 0.05, 0.03, 0.85]上。 这些是left和bottom以及小节的width和height中图形的分数。 我们将在第 6 章和“带有高级功能的绘图”中了解有关坐标系统的更多信息。 - 我们在
axes[1]上绘制第二张图,并使用自定义颜色colors = [(1, 0, 0), (0, 1, 0), (0, 0, 1)],它们是纯红色,绿色和蓝色。 cmap_name = 'custom_RGB_cmap'定义第一个用户定义的颜色表的名称。 如果我们必须注册它以将其包括在标准颜色表库中,这将很有用。cm = LinearSegmentedColormap.from_list(cmap_name, colors2, N=3)使用先前定义的三种颜色的列表定义颜色表。- 对于第二张图,我们将色条放置在以下坐标上:
cbaxs = [0.58, 0.05, 0.03, 0.85]。 - 同样,我们用
colors = [(1, 0.5, 0), (0.25, 0.5, 0.25), (0.8, 0.8, 0.25)]绘制第三张图并将它们放置在坐标cbax = [0.95, 0.05, 0.03, 0.85]上。 再次将红色,绿色和蓝色通道中的每种颜色与不同值的红色,绿色和蓝色组合在一起,以创建新的自定义颜色。
您应该看到以下图:
更多
以前,我们已经学习了如何创建离散的用户定义的颜色表。 现在让我们看看如何创建用户定义的连续色彩图。 区别在于颜色规格。 在离散的颜色表中,我们的 RGB 元组的数量与数据中簇的数量一样多,因此每种颜色代表一个簇。 但是,在连续的颜色表中,颜色必须沿着整个数据范围从光谱的一端逐渐移到另一端。
我们知道,每种颜色都用三个数字的元组表示:R,G 和 B 通道。 在某些情况下,第四通道alpha也用于表示颜色的透明度(或不透明度)。 这是我们需要指定颜色的方式。 让我们举个例子:
cdict1 = {'red': ((0.0, 0.0, 0.25), (0.5, 0.4, 0.4), (1.0, 0.8,
1.0)),
'green': ((0.0, 0.0, 0.25), (0.25, 0.5, 0.5), (0.75, 0.75,
0.75), (1.0, 0.9, 1.0)),
'blue': ((0.0, 0.0, 0.25), (0.5, 0.5, 0.5), (1.0, 0.75,
1.0))}
假设每个元组中的第一项是x,第二项是y0,第三项是y1。 在每种颜色组合中,x必须从 0.0 逐渐移至 1.0。 从顶部到底部的行必须从y1(顶部行)逐渐过渡到y0(下一行),从y0到y1在同一行中显示,然后在下一行中再次y1至yo应该是渐进的。 在红色的情况下,x从 0.0 移至 0.5,然后移至 1.0。 同样,y1从 0.25 移至 0.4、0.4、0.8,这也是渐进的。 我们可以在每种颜色中包含任意数量的元组。 在这种情况下,红色和蓝色分别具有三种,而绿色则具有四种。
同样,我们还定义了三个其他颜色字典,其中一个也带有alpha,只是为了演示所有可能的组合:
cdict2 = {'red' : ((0.0, 0.0, 0.0), (0.5, 0.0, 1.0), (1.0, 0.1, 1.0)),
'green': ((0.0, 0.0, 0.0), (1.0, 0.0, 0.0)),
'blue': ((0.0, 0.0, 0.1), (0.5, 0.5, 0.5), (1.0, 0.8, 0.8)) }
cdict3 = {'red': ((0.0, 0.0, 0.0), (0.25, 0.0, 0.0), (0.5, 0.8, 1.0),
(0.75, 1.0, 1.0),(1.0, 0.4, 1.0)),
'green': ((0.0, 0.0, 0.0), (0.25, 0.0, 0.0), (0.5, 0.9, 0.9),
(0.75, 0.0, 0.0), (1.0, 0.0, 0.0)),
'blue': ((0.0, 0.0, 0.4), (0.25, 1.0, 1.0), (0.5, 1.0, 0.8),
(0.75, 0.0, 0.0), (1.0, 0.0, 0.0))}
cdict4 = {'red': ((0.0, 0.0, 0.5), (0.5, 0.8, 1.0), (0.75, 1.0, 1.0),
(1.0, 0.9, 1.0)),
'green': ((0.0, 0.0, 0.5), (0.25, 0.75, 0.0), (0.5, 0.9,
0.9), (1.0, 0.0, 0.0)),
'blue': ((0.0, 0.0, 0.4), (0.25, 1.0, 1.0), (0.75, 0.0, 0.0),
(1.0, 0.0, 0.0)),
'alpha': ((0.0, 1.0, 1.0), (0.5, 0.4, 0.4), (1.0, 0.7, 1.0)) }
下面的代码块使用前面定义的四个颜色字典来绘制四个颜色表。 这与我们在离散色表的情况下所见相似。
读取Iris数据集和数字代码的映射类名称:
iris = pd.read_csv('iris_dataset.csv', delimiter=',')
iris['species'] = iris['species'].map({"setosa" : 0, "versicolor" : 1,
"virginica" : 2})
定义图形,布局,大小,并调整各图之间的空间:
fig, axs = plt.subplots(1,4, figsize=(16,6))
fig.subplots_adjust(left=0.0, bottom=0.0, right=0.95, top=0.94,
wspace=0.4)
定义一个函数以绘制图表:
def plot_graph(name, dictionary, axs, cbaxs):
custom = LinearSegmentedColormap(name, dictionary)
im = axs.scatter(iris.petal_length, iris.petal_width, s=100*iris.petal_length*iris.petal_width,
c=iris.species, cmap=custom)
caxs = plt.axes(cbaxs) # left, bottom, width and height
fig.colorbar(im, caxs)
绘制每种颜色组合的图形,并将其显示在屏幕上:
plot_graph('custom1', cdict1, axs[0], [0.2, 0.01, 0.01, 0.93])
plot_graph('custom2', cdict2, axs[1], [0.45, 0.01, 0.01, 0.93])
plot_graph('custom3', cdict3, axs[2], [0.7, 0.01, 0.01, 0.93])
plot_graph('custom4', cdict4, axs[3], [0.97, 0.01, 0.01, 0.93])
plt.show()
输出图如下所示:
处理图例
图例是给定轴域上每个图的描述。 每个轴域都有其自己的图例。 Matplotlib 提供了许多不同的方式来指定图例。 我们将涵盖尽可能多的组合,尽管我们将无法涵盖本书中的一整套可能性。
准备
导入以下必需的库:
import matplotlib as plt
import numpy as np
import matplotlib.patches as mpatches
from numpy.random import randn
操作步骤
以下代码块绘制了 11 种可以指定图例的不同方式:
- 定义图形的大小:
plt.figure(figsize=(15, 10))
- 使用内联标签绘制第一个图形:
plt.subplot(3,4,1)
line, = plt.plot([1, 2, 3], label='Inline label')
plt.legend()
- 使用
set_label方法用图例绘制第二张图:
plt.subplot(3,4,2)
line, = plt.plot([1, 2, 3])
line.set_label('Label via method')
plt.legend()
- 用两条线绘制第三个图形,并用标签列表绘制图例:
plt.subplot(3,4,3)
plt.plot([1, 2, 3])
plt.plot([3, 2, 1])
plt.legend(['Positive Slope', 'Negative Slope'])
plt.title('List of Labels')
- 用三条线绘制第四个图形,并用图柄和标签绘制图例:
plt.subplot(3,4,4)
line1, = plt.plot([1, 2, 3])
line2, = plt.plot([3, 2, 1])
line3, = plt.plot([2,2])
plt.legend((line3, line2, line1), ('Zero Slope', 'Negative Slope',
'Positive Slope'))
plt.title('Handles and Labels')
- 用三条线和图例以及部分手柄列表来绘制第五张图:
plt.subplot(3,4,5)
line_up, = plt.plot([1,2,3], label='Line 2')
line_down, = plt.plot([3,2,1], label='Line 1')
line_3, = plt.plot([2,3,4], label='no label')
plt.legend(handles=[line_up, line_down])
plt.title('Labels for given handles')
- 用三条线以及一部分手柄和标签绘制第六张图:
plt.subplot(3,4,6)
line_up, = plt.plot([1,2,3], label='Line 2')
line_down, = plt.plot([3,2,1], label='Line 1')
line_3, = plt.plot([2,3,4], label='no label')
plt.legend([line_up, line_down], ['Line Up', 'Line Down'])
plt.title('partial handles & labels')
- 用补丁作为标签绘制第七张图:
plt.subplot(3,4,7)
red_patch = mpatches.Patch(color='red', label='The red data')
plt.legend(handles=[red_patch])
plt.title('Patch as a label')
- 绘制第八张图, 在图例中带有类别标签:
plt.subplot(3,4,8)
z = randn(10)
blue_dot, = plt.plot(z, "bo", markersize=15)
## Put a white cross over some of the data.
white_cross, = plt.plot(z[:5], "w+", markeredgewidth=3,
markersize=15)
plt.legend([blue_dot, (blue_dot, white_cross)], ["Attr A", "Attr
A+B"])
plt.title('category labels')
- 在两列中将第九个图和图例放在图的顶部:
plt.subplot(3,4,9)
plt.plot([1, 2, 3], label="test1")
plt.plot([3, 2, 1], label="test2")
## Place a legend above this subplot, expanding itself to
## fully use the given bounding box.
plt.legend(bbox_to_anchor=(0, 1.02, 1., .102), #left, bottom, width,
height
ncol=2, mode="expand", borderaxespad=0.5)
ax = plt.gca()
ax.set_title('Legend on top', pad=20)
- 绘制第十张图,图例在图的右侧:
plt.subplot(3,4,10)
plt.plot([1, 2, 3], label="test1")
plt.plot([3, 2, 1], label="test2")
## Place a legend to the right of this smaller subplot.
plt.legend(bbox_to_anchor=(1.02, 1.0), borderaxespad=0)
plt.title('Legend on right')
- 绘制第十一张图,将图例分为多个图例:
plt.subplot(3,4,11)
line1, = plt.plot([1, 2, 3], label="Line 1", linestyle='--')
line2, = plt.plot([3, 2, 1], label="Line 2", linewidth=4)
## Create a legend for the first line.
first_legend = plt.legend(handles=[line1], loc=1)
## Add the legend manually to the current Axes. Repeated calls to plt.legend()
## will overwrite previous calls, so only last one remains
ax = plt.gca().add_artist(first_legend)
## Create another legend for the second line.
plt.legend(handles=[line2], loc=4)
plt.title('Split Legend')
- 清空第十二个绘图空间:
plt.subplot(3,4,12)
plt.axis('off')
- 调整绘图之间的空间,并在屏幕上显示图形:
plt.tight_layout(w_pad=5, h_pad=5)
plt.show()
工作原理
这是对十一个绘图的解释:
- 图 1:标签指定为线形图本身的一部分。
- 图 2:创建线对象后,将标签指定为直线轴域上的方法。
- 图 3:标签定义为
plt.legend()命令本身的列表。 - 图 4:句柄(轴域对象)和标签作为元组传递到
plt.legend()函数。 - 图 5:三个句柄中只有两个传递给
plt.legend(),因此图例中未显示line_3。 - 图 6:类似于图五,但句柄和标签都传递给
plt.legend()。 - 图 7:贴片用作标签。
mpatches.Patch()创建一个红色补丁。 - 图 8:绘制两个不同类别的数据并分别标记它们。
- 图 9:在图的顶部绘制图例,标签从左到右分布,并且不与标题重叠。
plt.legend(bbox_to_anchor=(0, 1.02, 1., .102), ncol=2, mode="expand", borderaxespad=0.5)使用bbox_to_anchor将标签放置在图的顶部(与图的大小成比例,从左起 0,从底部起 1.02,宽度为 1.0,高度为 0.102)。ncol=2指定标签应放在两列中,而不是两行中,这是默认设置。 - 图 10:再次使用
bbox_to_anchor()坐标,图例位于图的右侧。 - 图 11:将标签分为两部分,并将它们放置在不同的位置。 多次调用
plt.legend()将覆盖以前的图例; 只有最后一个占优势,因此不能用于将标签拆分和放置在其他位置。 其中之一必须通过ax=plt.gca().add_artist(first_legend)手动放置。plt.gca()获取当前轴域,然后add_artist()在该轴域上添加标签。 对于第二个标签,请使用标准plt.legend()。 - 图 12:由于没有第十二部分,我们必须清理轴线,壁虱和壁虱标签。 否则,它们将无任何显示地出现! 我们很快将在本章中学习轴线和壁虱。
以下是各图例与相应图例的外观:
更多
使用图例的另一个更常见的选项是plt.legend()上的loc参数。 该参数可以使用代码 0 到 10 来指定绘图上的不同位置。 它们每个都有一个文本描述,可以在 Matplotlib 文档上找到。
以下是两个可能选项的示例代码:
plt.legend(loc='best') or plt.legend(loc=0)
plt.legend(loc=‘upper right’) or plt.legend(loc=1)
自定义标签和标题
在本秘籍中,我们将学习如何自定义轴标签,刻度标签,图形和图形标题。 对于其中的一些自定义设置,我们将设置plt.rcParams默认参数。 但是,这些设置将处于活动状态,并适用于会话中的所有绘图。
准备
让我们导入所需的库并设置plt.rcParams(),这对于此秘籍也是必需的。 这些设置将适用于此会话中绘制的所有图:
import matplotlib.pyplot as plt
import numpy as np
plt.rcParams['figure.titlesize'] = 15
plt.rcParams['legend.fontsize'] = 12
plt.rcParams['axes.labelsize'] = 12
plt.rcParams['axes.labelweight'] = 'bold'
plt.rcParams['xtick.labelsize'] = 12
plt.rcParams['ytick.labelsize'] = 12
操作步骤
以下代码块绘制了三个带有各种标签的图,以演示如何进行自定义:
- 定义图形,布局和大小,并在图之间留出足够的空间:
fig, ax = plt.subplots(1, 3, figsize=(10,4))
fig.subplots_adjust(wspace=0.7)
- 使用自定义标签和标题在第一个轴域上绘制直方图:
ax[0].hist(np.random.randn(1000))
ax[0].set(xlabel='Bins', ylabel='Frequency')
atitle = ax[0].set_title('Histogram', fontstyle='italic',
fontsize=14)
plt.setp(atitle,color='blue')
- 在第二个轴域上绘制条形图:
## Plot the bars for men's data
menMue = [3, 10, 100, 500, 50]
menSigma = [0.75, 2.5, 25, 125, 12.5]
index = np.arange(len(menMue)) # the x locations for the groups
width = 0.35 # the width of the bars
p1 = ax[1].bar(index, menMue, width, color='r', bottom=0,
yerr=menSigma)
## Plot the bars for women's data
womenMue = [1000, 3, 30, 800, 1]
womenSigma = [500, 0.75, 8, 200, 0.25]
p2 = ax[1].bar(index + width, womenMue, width, color='y', bottom=0,
yerr=womenSigma)
## customize title and labels for the figure
atitle = ax[1].set_title('Scores by category and gender',
fontstyle='italic', fontsize=14)
plt.setp(atitle,color='blue')
ax[1].set(xticks=(index + width / 2), xticklabels=('C1', 'C2', 'C3',
'C4', 'C5'), yscale='log')
ax[1].legend((p1[0], p2[0]), ('Men', 'Women'), bbox_to_anchor=
(1.05,1))
- 在第三轴域上绘制散点图:
ax[2].scatter(np.random.rand(100),np.random.rand(100),
s=100*np.random.rand(100)*np.random.rand(100))
atitle = ax[2].set_title('Scatter Plot', fontstyle='italic',
fontsize=14)
plt.setp(atitle,color='blue')
- 设置图的标题:
ftitle= plt.suptitle('Figure Title', fontname='arial', fontsize=20,
fontweight='bold')
plt.setp(ftitle,color='green')
- 调整绘图之间的间距,并在屏幕上显示图形:
plt.tight_layout(pad=3, w_pad=5)
plt.show()
工作原理
以下是其工作原理的说明:
fig, ax = plt.subplots(1, 3, figsize=(10,4))定义图形布局。fig.subplots_adjust(wspace=0.5)调整子图之间的空间。ax[0].hist(np.random.randn(1000))在 0 轴域上绘制直方图,然后是 X 和 Y 轴的标签,然后是该图的标题。ax[0].set_title()除了标题文本外,还包含字体样式和大小参数,但没有color参数; 因此,我们使用plt.setp(atitle,color='blue')设置标题的颜色。plt.rcParams['axes.labelsize'] = 10和plt.rcParams['axes.labelweight'] = 'bold'设置所有图的 x 和 y 轴标签的字体大小和粗细。 在这里,我们仅对第一个图具有标签,因此,它们以fontsize或10的粗体显示。p1和p2是男性和女性在第一轴域上的柱状图。ax[1].set_xticks(ind + width / 2)设置刻度线,然后设置ax[1].set_xticklabels(('C1', 'C2', 'C3', 'C4', 'C5')),在 x 轴上设置ticklabels。 对于 x 轴,我们使用默认刻度和ticklabels作为对数刻度。 通常,我们为类别变量覆盖ticklables以给出有意义的名称。- 最后,
plt.suptitle()和plt.setp()为给定的字体名称,大小和颜色定义整体图形的标题。 plt.tight_layout(pad=3)调整绘图之间的间隔,pad=3调整图形标题与各个绘图标题之间的间隔,以使它们之间没有重叠。
我们得到的输出如下:
更多
字体fontstyle,fontsize,fontweight以及字体颜色应用于轴标签,刻度标签,轴域标题和图形标题的选项组合有多种可能性。 利用所有这些功能,我们可以绘制专业的质量可视化图像。
使用自动缩放和轴限制
Matplotlib 自动将 x 和 y 轴的整个数据范围拟合到输入数据中,将其拆分为桶,并相应地显示刻度和刻度标签。 有时,我们可能希望在任一轴域上更紧密地查看特定范围的数据,而不是完整的数据范围。 在本秘籍中,我们将学习如何做。
准备
让我们导入所需的库:
import numpy as np
import matplotlib.pylab as plt
from matplotlib.ticker import FuncFormatter
操作步骤
以下代码显示了相同输入数据的两个图,但是第一个使用默认设置,因此它在 x 和 y 轴上都显示了完整范围的数据,而第二个图限制了 x 和 y 轴范围:
- 为图表准备数据:
x = np.linspace(-50,50,500)
y = x**2 + np.cos(x)*100
- 定义一个函数以在打印到绘图上之前格式化数字数据:
def Num_Format(x, pos):
"""The two arguments are the number and tick position"""
if x >= 1e6:
string = '${:1.1f}M'.format(x*1e-6)
else:
string = '${:1.0f}K'.format(x*1e-3)
return string
- 将先前定义的函数应用于
formatter,并使用大小和布局定义图形:
formatter = FuncFormatter(Num_Format)
fig, axs = plt.subplots(1,2, figsize=(8,5))
- 使用自动缩放在第一个轴域上绘制折线图:
axs[0].plot(x, y**2) axs[0].yaxis.set_major_formatter(formatter)
axs[0].set_title('Full Data/Autoscale')
- 再次绘制同一图,并在 x 和 y 轴上都施加限制:
axs[1].plot(x, y**2)
axs[1].set(xlim=(-5,5), ylim=(0,10000), title='X and Y limited')
axs[1].yaxis.set_major_formatter(formatter)
- 在屏幕上显示该图:
plt.show()
工作原理
- 对于 x 轴坐标,
x = np.linspace(-50,50,500)创建 500 个点,它们之间的等距距离在-50 到+50 之间。 def Num_Format(x, pos)是根据数字是千位还是数百万位将大数字格式化为$K或$M的函数。FuncFormatter(Num_Format)是一个 matplotlib 函数,它使用用户定义的函数货币作为参数,然后将此FuncFormatter应用于 x 或 y 轴上,在其上使用axs[0].yaxis.set_major_formatter(formatter)来格式化数字。axs[0].plot(x, y**2)使用 x 和 y 轴的默认设置在轴域 0 上绘制图形,因此它显示来自输入的全部数据。axs[1].plot(x, y**2)在第一个轴域上再次绘制相同的图形。axs[1].set_xlim(-5,5)在 x 轴上将数据限制从 -5 设置为 +5,axs[1].set_ylim(0,10000)在 y 轴上将数据限制从 0 设置为 10,000。 这些限制设置为第一轴域上的图。
您应该得到两个图,如下所示:
自定义刻度和刻度标签
到目前为止,我们已经看到 Matplotlib 根据输入数据自动放置刻度和刻度标签。 在本秘籍中,我们将学习如何在 x 和 y 轴上自定义这些默认设置,以用于分类变量和数值变量。
准备
让我们导入所需的库:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import (MultipleLocator, FormatStrFormatter,
AutoMinorLocator)
from matplotlib.ticker import FuncFormatter
操作步骤
以下代码块绘制了两个男人和女人的条形图。 在 y 轴上,绘制了平均工资,在 x 轴上,绘制了男女类别中的各个类别。 因此,我们在 y 轴上有一个数字变量,在 x 轴上有一个分类变量。
以下代码块对 y 轴上的刻度和刻度标签使用默认设置,但对 x 轴使用自定义设置:
- 设置数据并绘制男性数据的条形图:
menMue = [3, 10, 100, 500, 50]
menSigma = [0.75, 2.5, 25, 125, 12.5]
fig, ax = plt.subplots()
ind = np.arange(len(menMue)) # the x locations for the groups
width = 0.35 # the width of the bars
p1 = ax.bar(ind, menMue, width, color='lightblue', bottom=0,
yerr=menSigma)
- 设置数据并绘制女性数据的条形图:
womenMue = [1000, 3, 30, 800, 1]
womenSigma = [250, 0.75, 8, 200, 0.25]
p2 = ax.bar(ind + width, womenMue, width, color='orange', bottom=0,
yerr=womenSigma)
- 设置图形的标题,标签和图例:
ax.set_title('Scores by group and gender')
ax.set(xticks=(ind + width / 2), xticklabels=('C1', 'C2', 'C3',
'C4', 'C5'), yscale='log')
ax.legend((p1[1], p2[1]), ('Men', 'Women'), bbox_to_anchor=(1.3,1))
- 在屏幕上显示该图:
plt.show()
工作原理
这是代码的说明:
ax.set_xticks(ind + width / 2)设置将每个刻度准确放置在 x 轴上的位置。 由于ind是根据男性数据定义的,因此会将刻度线放置在男性条的中间(浅蓝色),然后通过向每个索引中添加width / 2,将刻度在两个条之间移动。ax.set_xticklabels(('C1', 'C2', 'C3', 'C4', 'C5'))在 x 轴上设置刻度标签:
更多
让我们再举一个例子,说明如何自定义刻度线的大小,长度和颜色。 以下代码块显示了三个图表; 第一个使用刻度和刻度标签的默认设置,第二个被自定义以显示主要和次要刻度,第三个被自定义以指定主要和次要刻度的长度,厚度和颜色:
- 定义用于格式化数字数据的函数:
def Num_Format(x, pos):
"""The two arguments are the number and tick position"""
if x >= 1e6:
string = '${:1.1f}M'.format(x*1e-6)
else:
string = '${:1.0f}K'.format(x*1e-3)
return string
- 定义一个函数来绘制图形:
def plot_graph(axes, axis, major_step_size, minor_step_size):
majorLocator = MultipleLocator(major_step_size)
minorLocator = MultipleLocator(minor_step_size)
if axis == 'x':
axes.xaxis.set_major_locator(majorLocator)
axes.xaxis.set_minor_locator(minorLocator)
else:
axes.yaxis.set_major_locator(majorLocator)
axes.yaxis.set_minor_locator(minorLocator)
axes.yaxis.set_major_formatter(formatter)
- 设置图的数据:
x = np.linspace(-50,50,500)
y = x**2 + np.cos(x)*100
- 定义图形,布局和大小,并调整各图之间的空间:
fig, axs = plt.subplots(1,3, figsize=(15,5))
fig.subplots_adjust(wspace=0.5)
- 使用 y 轴应用
formatter绘制图形:
formatter = FuncFormatter(Num_Format)
axs[0].plot(x, y**2)
axs[0].set_title('Default Ticks and Ticklabels')
axs[0].yaxis.set_major_formatter(formatter)
- 在第二轴域上用主要和次要刻度画线形图:
axs[1].plot(x, y**2)
plot_graph(axs[1], 'y', 500000, 250000)
plot_graph(axs[1], 'x', 10, 2)
axs[1].set_title('Major and Minor Ticks')
- 使用自定义刻度和刻度标签在第三个轴域上绘制折线图:
axs[2].plot(x, y**2)
plot_graph(axs[2], 'x', 10, 2)
minorLocator = AutoMinorLocator()
axs[2].xaxis.set_minor_locator(minorLocator)
axs[2].tick_params(which='major', length=10, color='g')
axs[2].tick_params(which='minor', length=4, color='r')
axs[2].tick_params(which='both', width=2)
axs[2].set_title('Customised Ticks')
axs[2].grid(True)
- 在屏幕上显示该图:
plt.show()
这是代码及其工作方式的说明:
- 零轴域上的第一个绘图使用默认设置,它会自动为 y 轴选择一百万个仓位,并为 x 轴选择 20 个单位仓位,并相应地放置刻度和刻度标签 。
- 轴域 1 上的第二个图
majorLocator = MultipleLocator(500000)指定应以500000间隔放置主要刻度线,axs[1].yaxis.set_major_locator(majorLocator)在 y 轴主要刻度上设置此间隔。majorFormatter = FormatStrFormatter('%d')指定要显示的刻度标签编号的格式,axs[1].yaxis.set_major_formatter(majorFormatter)将格式应用于 y 轴的主刻度标签。 - 对于 x 轴重复相同的过程,其中
10单元箱用于主要刻度,而2单元用于次刻度。 - 第三幅图与第二幅图相似,只将次要刻度线限制在 x 轴上,并为主要和次要刻度线设置了长度,宽度和颜色设置。
tick_params()设置这些参数,和参数which=指定要应用的主要,次要或两个刻度。
这是前面代码的生成的输出:
自定义轴线
默认情况下,Matplotlib 在图的顶部,底部,左侧和右侧显示所有四个轴线,并在其周围创建一个边界框。 它仅在左侧(y 轴)和底部(x 轴)上显示刻度和刻度标签。 但是,它允许我们自定义它们的位置,并根据需要省略任何轴线。
准备
我们将绘制六个具有相同数据的图,但为轴线设置各种选项。
导入以下必需的库:
import numpy as np
import matplotlib.pyplot as plt
操作步骤
以下代码块显示六个具有相同数据,但轴线的选项不同的图:
- 设置图的数据:
theta = np.linspace(0, 2*np.pi, 128)
y = np.sin(theta)
- 定义图形的大小:
fig = plt.figure(figsize=(8,6))
- 定义第一个轴域,并用默认的轴线绘制正弦波:
ax1 = fig.add_subplot(2, 3, 1)
ax1.plot(theta, np.sin(theta), 'b-*')
ax1.set_title('default spines')
- 定义用于绘制图形的函数:
def plot_graph(axs, title, lposition, bposition):
ax = fig.add_subplot(axs)
ax.plot(theta, y, 'b-*')
ax.set_title(title)
ax.spines['left'].set_position(lposition)
ax.spines['right'].set_visible(False)
ax.spines['bottom'].set_position(bposition)
ax.spines['top'].set_visible(False)
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')
- 绘制五个具有不同轴线位置的图形:
plot_graph(232, 'centered spines', 'center', 'center')
plot_graph(233, 'zeroed spines', 'zero', 'zero')
plot_graph(234, 'spines at axes [0.25, 0.75]', ('axes', 0.25),
('axes', 0.75))
plot_graph(235, 'spines at data [1.0, -1.0]', ('data', 1.0),
('data', -1.0))
plot_graph(236, 'adjusted spines', ('outward', 10), ('outward', 10))
- 调整绘图之间的空间,并在屏幕上显示图形:
plt.tight_layout()
plt.show()
工作原理
- 曲线 1 使用默认设置的轴线。 因此,它将显示所有四个轴线,左侧和底部分别代表 y 和 x 轴,并带有适当的刻度和刻度标签。
- 在曲线 2 中,使用
set_visible(False)方法使顶部和右侧轴线不可见。set_position('center')将 x 和 y 轴放置在相应数据范围之间。 在这种情况下, y 轴上的数据范围是 -1 到 +1,所以中心点是 0,而 x 轴上的数据范围是 0 到 6,所以中心点是3。 因此,交点为(3, 0)。 - 线形图 3 放置左轴线和底轴线,使它们在
(0, 0)相交。 - 线形图 4 以在 x 轴上的 0.25 范围和在 y 轴上的 0.75 范围内相交的方式放置左轴线和底轴线。
[0.25, 0.75]为0.25 * x 范围 = 0.25 * (0 到 6) = 1.5,0.75 * y 范围 = 0.75 * (-1 到 1) = 0.5。 因此,交点为(1.5, 0.5)。axes选项基本上将 x 轴的底部 25%(第一个四分位数)和 y 轴的底部 75%(第三个四分位数)设置为最低。 - 在图 5 中,我们使用
data选项指定输入数据中的位置。 因此,它将左脊和下脊置于(1, -1)交点。 - 在图 6 中,我们使用
outward参数将轴线放置在远离图形的位置指定数量的单位; 在这里是10:
双生轴域
有时,我们可能希望在同一轴域上绘制两个图表,但是数据规模不同。 如果我们在左右轴线上使用具有相同比例尺的标准图,则由于数据比例尺的巨大差异,图表可能看起来不正确。 在这种情况下,我们可以使用 Matplotlib 提供的双生轴域功能。 我们将在本秘籍中学习如何使用它。
在此示例中,我们将在制造工厂中使用一个月的产品缺陷数据。 我们将通过原因代码(例如 0 到 5,代表生产缺陷产品的各种原因)和累积百分比折线图(缺陷代码上汇总的缺陷产品总数)绘制条形图。
轴域联动有三种选择:
twinx:为两个图形共享 x 轴,而左轴和右轴表示两个不同的比例twiny:为两个图形共享 y 轴,而顶部和底部轴表示两个比例no sharing:其中一张图使用底部轴和左轴,第二张图使用顶部轴和右轴
我们将学习如何在本秘籍中实现所有三种可能性。
准备
我们将使用给定月份的制造工厂中的产品缺陷数据。 它具有缺陷原因代码和许多缺陷。 因此,我们将通过缺陷原因代码绘制条形图以显示缺陷数量,并绘制一条线形图以累积缺陷占总缺陷的百分比。 显然,缺陷数量和累积百分比的数据范围会发生很大变化,因此,通用的 y 轴无法提供正确的数据图。 在这种情况下,将轴域缠绕在一起可以进行救援。
我们将绘制两个不同的图; 本节中一个使用twinx(),另一个使用twiny()。 我们将学习如何在任何轴域上绘制no sharing的第三个选项。本秘籍还有更多...* 部分。
导入所需的库:
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator
操作步骤
这是绘制所需图形所涉及的步骤:
- 准备绘图数据:
x = [0, 1, 2, 3, 4, 5]
y = [19, 12, 6, 4, 3, 2]
y1 = [41, 67, 80, 89, 96, 100]
- 定义图形和所需的轴域,包括双生轴域:
fig = plt.figure(figsize=(10,6))
ax1 = plt.subplot(121) # first plot
ax2 = ax1.twinx() # share x axis
ax3 = plt.subplot(122) # second plot
ax4 = ax3.twiny() # share y axis
- 使用
twinx()选项绘制条形图和折线图:
b = ax1.bar(x, y, label='Number of Defects')
l, = ax2.plot(x, y1, color='g', lw=5, label='Cumulative Defects as %')
- 设置第一个图的标签和图例:
majorLocator = MultipleLocator(2)
ax1.yaxis.set_major_locator(majorLocator)
ax1.set(xlabel='Defect Reason Codes', ylabel='Number of Defects')
ax2.set(ylabel='Cumulative Defects as %')
ax1.legend([b, l],['Number of Defects','Cumulative Defects as %'],
loc=5)
- 使用
twiny()选项绘制条形图和折线图:
b1 = ax3.barh(x, y, label='Number of Defects')
l1, = ax4.plot(y1, x, color='g', lw=5, label='Cumulative Defects as
%')
- 设置第二个绘图的标签和图例:
ax3.xaxis.set_major_locator(majorLocator)
ax3.set(xlabel='Number of Defects', ylabel='Defect Reason Codes')
ax4.set(xlabel='Cumulative Defects as %')
ax3.legend([b1, l1], ['Number of Defects', 'Cumulative Defects as
%'], loc=1)
ax3.set_ylim(-1,6)
- 打印图形的标题,并调整两个图形之间的空间:
plt.suptitle('Product Defects - August 2018', fontname='arial',
fontsize=20,
fontweight='bold')
plt.tight_layout(w_pad=5, pad=3)
- 在屏幕上显示该图:
plt.show()
工作原理
这是前面代码的解释:
x = [0, 1, 2, 3, 4, 5]是产品缺陷代码的列表,y = [19, 12, 6, 4, 3, 2]是给定月份中每个缺陷代码的缺陷数量的列表,y1 = [41, 67, 80, 89, 96, 100]是累积缺陷占总缺陷百分比的列表。ax1 = plt.subplot(121)定义第一个图的主轴域,121表示它是1 x 2网格中的第一个图。ax2 = ax1.twinx()定义第一个绘图的双生轴域。 它不会在物理上创建另一个轴域,而是仅使用主轴域,并将右轴线用作此新逻辑轴域ax2的 y 轴,并共享底部轴线作为ax1和ax2的 x 轴。ax3 = plt.subplot(121)定义第二个绘图的主轴域,122表示它是1 x 2网格中的第二个绘图。ax4 = ax3.twinx()定义第二个绘图的双生轴域。 同样,它不会在物理上创建其他轴域,而仅使用主轴域,并将右脊用作次轴域ax4,并为ax3和ax4共享底部轴线作为 x 轴。b = ax1.bar(x, y, label='Number of Defects')绘制条形图,缺陷代码与缺陷数量的关系。l, = ax2.plot(x, y1, color='g', lw=5, label='Cumulative Defects as %')绘制线形图:缺陷代码与累积缺陷%。majorLocator = MultipleLocator(2)定义主要刻度线的步长为 2。ax1.yaxis.set_major_locator(majorLocator)向第一幅图的主轴域的 y 轴应用主定位器。ax1.set(xlabel='Defect Reason Codes', ylabel='Number of Defects')为主轴域设置 x 和 y 轴标签。ax2.set(ylabel='Cumulative Defects as %')为双生轴域设置ylabel,并且由于共享 x 轴; 再次没有标签在这里。ax1.legend([b, l], ['Number of Defects', 'Cumulative Defects as %'], loc=5)设置主轴域的图例:[b,l]分别是条形图和折线图的句柄列表。['Number of Defects', 'Cumulative Defects as %']分别是条形图和折线图的标签列表。loc=5指定图例应以右对齐的方式放置在轴域的中心。
b1 = ax3.bar(x, y, label='Number of Defects')绘制条形图,缺陷代码与缺陷数量的关系。l1, = ax4.plot(x, y1, color='g', lw=5, label='Cumulative Defects as %')绘制折线图,缺陷代码与累积缺陷%。majorLocator = MultipleLocator(2), 定义主要刻度线的步长为 2。ax3.yaxis.set_major_locator(majorLocator)将主定位器应用于第一幅图的主轴域的 y 轴。ax3.set(xlabel='Defect Reason Codes', ylabel='Number of Defects')设置主轴域的 x 和 y 轴标签。ax4.set(ylabel='Cumulative Defects as %')为双生轴域设置ylabel,并且由于 x 轴已共享,此处不再有标签。ax3.legend([b1, l1], ['Number of Defects', 'Cumulative Defects as %'], loc=1)设置第二个绘图主轴域的图例。ax3.set_ylim(-1,6)设置第二个图的主轴域的 y 轴的上下限。plt.suptitle('Product Defects - August 2018', fontname='arial', fontsize=20, fontweight='bold')用各种属性(例如字体名称,大小和粗细)绘制整个图形的标题。plt.tight_layout(w_pad=5, pad=3)调整绘图之间的空间,以使它们没有重叠:w_pad=5指定两个图之间的间隙量。pad=3在图的顶部指定为标题腾出空间的数量空间。
plt.show()在屏幕上显示图形。
运行前面的代码后,您应该在屏幕上看到下图:
更多
我们已经了解了如何使用双生轴域功能分别共享 x 和 y 轴。 现在,让我们看一下不共享两个轴的选项,而是对一个图形使用左轴线和底轴线,对另一个图形使用上轴线和右轴线。 所有四个轴线使用不同的刻度,因此ticks和ticklabels不同。
在此示例中,我们将使用熟悉的Iris数据集。 众所周知,有四个属性:petal_width,petal_leangth,sepal_width和sepal_length。 因此,正如我们在本书中多次看到的那样,当我们使用petal_width和petal_length绘制散点图时,我们看到了三个不同的簇,但是当我们使用sepal_length和sepal_width绘制散点图时,我们不会观察到任何此类簇。
这是绘制此代码所需的代码。 由于我们已经看过很多次了,因此这里不再逐行解释。 唯一的区别是ax1 = ax.twinx().twiny()。 而不是使用twinx()或twiny(),我们都使用了两者,以便将上轴域和右轴域用于此新逻辑轴域(ax1),而将左轴域和底轴域用于主轴域(ax):
import matplotlib.pyplot as plt
import pandas as pd
iris = pd.read_csv('iris_dataset.csv', delimiter=',')
iris['species'] = iris['species'].map({"setosa" : 0, "versicolor" : 1,
"virginica" : 2})
plt.figure(figsize=(8,6))
ax = plt.subplot(111)
h1 = ax.scatter(iris.petal_width, iris.petal_length, s=5*iris.petal_width*iris.petal_length, c='b')
ax1 = ax.twinx().twiny()
h2 = ax1.scatter(iris.sepal_width, iris.sepal_length,
s=5*iris.sepal_width*iris.sepal_length, c='g')
ax.legend([h1, h2], ['petals', 'sepals'], loc='best')
plt.show()
运行前面的代码后,您应该在屏幕上看到下图:
从该图可以看出,使用花瓣的宽度和长度绘制的蓝色点确实形成了三个不同的簇,而以萼片的宽度和长度绘制的绿色点散布在各处,没有任何特定的图案!
Please also note the scale of data on each of the four axes. All of them have a different scale!
使用图案填充
图案填充用于填充指定区域中的图案。 我们将在本秘籍中学习如何使用它。
准备
导入所需的库:
import matplotlib.pyplot as plt
import numpy as np
操作步骤
以下代码块创建了五个表示领带的图表,并在上面印刷了不同的颜色和图案:
## Set up the data
x = np.array([0.2, 0.4, 0.6, 0.8, 0.5])
y = [1, 6, 6, 1, 0]
## Plot a tie graph 5 times with different colors and hatches
plt.fill(x+1, y, color='g', hatch='+*')
plt.fill(x+2, y, color='b', hatch='-o')
plt.fill(x+3, y, color='y', hatch='+x')
plt.fill(x+4, y, color='r', hatch='\\')
plt.fill(x+5, y, color='m', hatch='Ox')
plt.title('Hatch Demo')
plt.show()
工作原理
x和y是表示二维空间上的五个点的列表。 这五个点所覆盖的区域会形成平局。 使用plt.fill()方法中的hatch自变量填充颜色和图案:
使用标注
通过指向文本中描述的区域,标注用于描述绘图上的特定细节。 我们将在秘籍中介绍一个简单的示例。 在后面的章节中将进行更详细的描述。
准备
导入所需的库:
import matplotlib.pyplot as plt
import numpy as np
操作步骤
以下代码块显示了一个绘图,在该绘图上用箭头标注了一个点(3, 0):
plt.plot(theta, np.sin(theta), 'b-*')
a = plt.annotate("(3,0)", xy=(3, 0), xycoords='data', xytext=(4.0,
0.5), textcoords='data',
arrowprops=dict(arrowstyle="->", color="green", lw=5,
connectionstyle=("arc3,rad=0.")))
plt.setp(a, size=25)
plt.show()
工作原理
这是代码的说明:
plt.annotate()方法使用指定的详细信息标注图形。(3, 0)指定要显示为描述的文本。xy = (3, 0)指定图形上要标注的点的坐标。xycoords='data'指定所指定的xy坐标是相对于数据(输入数据中的点)的。arrowprops()指定从文本到要标注的点要使用的箭头的style,linewidth,color,connectionstyle。plt.setp()将文本(3, 0)的字体大小设置为25。
通过运行前面的代码,我们得到以下输出:
使用样式表
我们已经学习了如何使用图形的各种属性来创建专业图形。 但是,找出这么多不同的组合并获得漂亮的图形非常耗时。 Matplotlib 提供了称为样式表的现成模板的列表,这些模板使用各种属性的预定义组合。 在本秘籍中,我们将学习如何使用这些预定义的样式表。
You can use print(plt.style.available) to get the list of all the available style sheets.
准备
导入所需的库:
import matplotlib.pyplot as plt
import numpy as np
操作步骤
以下代码块绘制了四种不同类型的图,所有图都具有相同的样式表,以演示如何使用样式表:
- 定义要在此会话中应用于所有图形的样式:
plt.style.use('seaborn-bright')
- 定义图形,大小并调整图之间的空间:
fig, ax = plt.subplots(1, 4, figsize=(10,5))
fig.subplots_adjust(wspace=0.5)
- 在第一个轴域上绘制直方图:
ax[0].hist(np.random.randn(1000))
- 在第二个轴域上绘制三个折线图:
for i in range(3):
ax[1].plot(np.random.rand(10))
ax[1].legend(['a', 'b', 'c'], loc='lower left')
- 在第三个轴域上绘制散点图:
ax[2].scatter(np.random.rand(100),np.random.rand(100),
s=100*np.random.rand(100)*np.random.rand(100))
- 在第四个轴域上绘制饼图:
labels = ['SciFi', 'Drama', 'Thriller', 'Comedy', 'Action',
'Romance']
sizes = [5, 15, 10, 20, 40, 10] # Add upto 100%
explode = (0, 0, 0, 0, 0.1, 0)
ax[3].pie(sizes, explode=explode, labels=labels, autopct='%1.0f%%',
pctdistance=0.7,
shadow=True, startangle=90)
ax[3].axis('equal') # Equal aspect ratio ensures that pie is drawn
as a circle.
- 设置图形的标题并将其显示在屏幕上:
plt.suptitle('seaborn-bright', color='b', weight='bold')
plt.show()
工作原理
这是刚刚给出的代码的说明:
plt.style.use('seaborn-bright')设置要使用的特定样式表。 相同的样式表将应用于此会话中的所有绘图。 在此示例中,我们使用seaborn-bright样式表。
剩余的代码绘制了四个图形,正如我们之前所看到的。
如您所见,我们没有为任何图形属性指定任何特定参数。 它们都是从我们一开始提供的样式表中借用的:
更多
为了演示更多样式表,下面的代码块使用与之前相同的四个图,但是应用style_list中指定的样式表列表。
由于相同的代码将重复多次,因此我们定义一个函数,并在每次使用不同style参数的for循环中调用它:
style_list = ['classic', 'dark_background', 'ggplot', 'grayscale',
'seaborn']
def plot_the_graph(style):
np.random.seed(0)
fig, ax = plt.subplots(1, 4, figsize=(12,5))
fig.subplots_adjust(wspace=0.5)
ax[0].hist(np.random.randn(1000))
for i in range(3):
ax[1].plot(np.random.rand(10))
ax[1].legend(['a', 'b', 'c'], loc='lower left')
ax[2].scatter(np.random.rand(100),np.random.rand(100),
s=100*np.random.rand(100)*np.random.rand(100))
labels = ['SciFi', 'Drama', 'Thriller', 'Comedy', 'Action',
'Romance']
sizes = [5, 15, 10, 20, 40, 10] # Add upto 100%
explode = (0, 0, 0, 0, 0.1, 0) # only "explode" the 2nd slice (i.e.
'Hogs')
ax[3].pie(sizes, explode=explode, labels=labels, autopct='%1.0f%%',
pctdistance=0.7,
shadow=True, startangle=90)
ax[3].axis('equal') # Equal aspect ratio ensures that pie is drawn
as a circle.
plt.suptitle(style)
plt.show()
for style in style_list:
with plt.style.context(style):
plot_the_graph(style)
执行前面的代码后,您应该在屏幕上看到以下五个单独的图形,每个图形具有style_list中指定的不同样式:
使用面向对象的 API 进行绘图
在本章中,我们将使用以下秘籍来学习pyplot API 和面向对象的 API 之间的区别:
- 使用
pyplot和面向对象的 API 绘制相关矩阵 - 使用面向对象的 API 绘制补丁
- 使用面向对象的 API 绘制集合
介绍
如第 1 章,“Matplotlib 的剖析”中所述,Matplotlib 具有三层架构。 顶层称为脚本层,并通过pyplot() API 实现。 该 API 是为没有太多编程经验的用户设计的,因此它使用户免受使用底部两层(艺术家和后端)创建和渲染图的复杂性的困扰。 对于使用高级功能(例如补丁,集合,使用事件,回调,动画和窗口小部件的交互式绘图)的复杂应用,我们将必须使用面向对象的 API。 但是,要利用此 API 的全部潜能,需要大量的 Python 编码经验。 随着新版本 Matplotlib 的发布,越来越多的这些功能正在移入pyplot API 中,从而减少了对面向对象 API 的依赖。
面向对象的 API 名称有点让人困惑,因为它可能给人以pyplot API 不是面向对象的印象,这是不正确的。 这仅意味着面向对象的 API 会直接使用艺术家和后端层,而绕过脚本层(不使用pyplot API)。 这提供了使用 Matplotlib 提供的完整功能的灵活性,而pyplot API 提供了它的一个子集。
应该注意的是,对于任何绘图或图形,都不必是pyplot API 或面向对象的 API; 它可以是两者的结合。 实际上,到目前为止,我们开发的许多图形都将两者结合使用。 当我们必须使用复杂的网格结构在图形中放置图时,我们使用了面向对象的 API。 当分别绘制每个图形并创建图形对象和基础画布时,我们使用了pyplot API。 一旦我们看到了两种 API 之间的差异,您将了解两种 API 的结合使用。
使用pyplot和面向对象的 API 绘制相关矩阵
在本秘籍中,我们将学习pyplot与面向对象的 API 之间的区别。 我们将首先使用pyplot API,然后使用面向对象的 API 绘制相同的相关矩阵。 我们将使用相同的Wine Quality数据集绘制相关矩阵。
准备
为pyplot API 导入以下库:
import pandas as pd
import matplotlib.pyplot as plt
导入以下库以获取面向对象的 API:
import pandas as pd
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure
from IPython.core.display import display
matplotlib.backends具有一组支持的后端。 在这里,我们要导入FigureCanvasAgg,它提供了绘制图形的空间并将其映射到定义的后端设备。
IPython.core.display可以将绘图显示在输出设备上。
操作步骤
以下代码块使用 pandas 读取数据并使用pyplot API 绘制相关矩阵。 这与我们在第 2 章“基本绘图入门”中绘制热图的方式相同:
- 将数据从 CSV 文件读取到 Pandas 数据帧中:
wine_quality = pd.read_csv('winequality.csv', delimiter=';')
- 获取
wine_quality所有属性的相关矩阵:
corr = wine_quality.corr()
- 定义图形及其大小,并绘制图像和相关的颜色条:
plt.figure(figsize=(12,9))
plt.imshow(corr,cmap='hot')
plt.colorbar()
- 设置图形的标题和刻度,并在屏幕上显示:
plt.title('Correlation Matrix')
plt.xticks(range(len(corr)),corr.columns, fontsize=10, fontweight='bold',rotation=45)
plt.yticks(range(len(corr)),corr.columns)
plt.show()
前面的代码块中的所有命令都是我们熟悉的,因为我们已经在第 2 章,“基本绘图”和第 4 章,“为发布质量开发可视化”中学习了它们。
以下代码块使用面向对象的 API(不使用pyplot API)绘制相同的相关图:
- 将数据从 CSV 文件读取到 Pandas 数据帧中:
wine_quality = pd.read_csv('winequality.csv', delimiter=';')
- 获取
wine_quality所有属性的相关矩阵:
corr = wine_quality.corr()
- 定义图形的大小:
fig = Figure(figsize=(12,9))
- 将图形附加到画布上:
FigureCanvas(fig)
- 定义图中的轴域,我们需要绘制相关图,并绘制相关图和颜色条:
axs = fig.add_subplot(111)
corimage = axs.imshow(corr,cmap='hot')
fig.colorbar(corimage)
- 设置
ticks和ticklabels:
axs.set(xticks=range(len(corr)), yticks=range(len(corr)),
title='Correlation Matrix')
fontd = {'fontsize': 10,
'fontweight': 'bold',
'rotation': 45}
axs.set_xticklabels(corr.columns, fontdict=fontd)
axs.set_yticklabels(corr.columns)
- 在屏幕上显示该图:
display(fig)
工作原理
pyplot API 代码块是不言自明的。 这是输出图表:
以下是面向对象的 API 代码块的说明:
Figure(figsize=(12,9))实例化大小为(12, 9)的图形对象。FigureCanvas(fig)附加画布(需要绘制图形的区域,该区域最终显示在连接的后端设备上)。 对于pyplotAPI,我们无需这样做,因为pyplotAPI 会处理它。fig.add_subplot(111)在先前创建的图形对象内创建轴域对象。 请注意,我们可以在一个图形对象内创建多个轴域对象。 在这里,我们只创建一个轴域,因为我们只绘制一个图。axs.imshow(corr,cmap='hot')使用标准色表hot将相关矩阵创建为图像。fig.colorbar(corimage)将颜色条附加到之前创建的图像。- 要为 x 和 y 轴创建
ticks和ticklabels,pyplotAPI 具有plt.xticks和plt.yticks方法,它们同时具有刻度位置和刻度线作为参数,并使用一个命令进行管理。 但是,对于面向对象的 API,我们将不得不单独进行。 axs.set(xticks=range(len(corr)), yticks=range(len(corr)), title='Correlation Matrix')定义了 x 和 y 轴刻度和图形标题。 它需要的刻度声与相关矩阵中的属性一样多。fontd是具有要应用于xticklabels的所有属性的字典。 如果需要,我们也可以对yticklabels执行相同的操作。axs.set_xticklabels(corr.columns, fontdict=fontd)用定义的属性设置xticklabels。axs.set_yticklabels(corr.columns)将 y 轴设置为ticklabels。
执行前面的代码后,您应该看到以下图表:
使用面向对象的 API 绘制补丁
Matplotlib 使用补丁和集合类提供了一些特殊类型的图。 在本秘籍中,我们将学习如何使用面向对象的 API 使用patches。 在下一个秘籍中,我们将学习collections。
准备
我们将需要为该秘籍导入以下库:
from IPython.core.display import display
from matplotlib.backends import backend_agg
from matplotlib.patches import Ellipse, Polygon
操作步骤
以下代码块在同一图中将两个补丁绘制为单独的图:
- 使用
figure_manager定义图形及其大小,然后将其附加到画布上:
figure_manager = backend_agg.new_figure_manager(1, figsize=(12,6))
fig = figure_manager.canvas.figure
- 定义第一个轴域并在其上绘制一个椭圆形色块:
axs1 = fig.add_subplot(121)
axs1.add_patch(Ellipse((3, 1.0), 4, 1.0, hatch='/', facecolor='g'))
## centre=(3, 1.0), width=4, height=1.0
axs1.set_xlim((0, 6))
axs1.set_ylim((0, 2.5))
- 定义第二个轴域并在其上绘制一个补丁:
axs2 = fig.add_subplot(122)
axs2.add_patch(Polygon([[0, 0], [4, 1.1], [6, 2.5], [2, 1.4]],
color='b', lw=5, fill=False, hatch='+*'))
axs2.set_xlim((0, 6))
axs2.set_ylim((0, 2.5))
- 在屏幕上显示该图:
display(fig)
工作原理
以下是上述代码及其工作方式的说明:
- 为了定义图形和画布,我们在本秘籍中使用另一种方法
new_figure_manager(),只是为了演示 Matplotlib 提供的多种选项。 我们也可以使用与先前秘籍相同的方法。 这种方法更适合于循环处理多个图形。 它使用参数作为图形编号和图形大小。 fig.add_subplot(121)实例化第一个图形的第一个轴域。axs1.add_patch(Ellipse((3, 1.0), 4, 1.0, hatch='/', facecolor='g'))在axs1上添加了椭圆形补丁。(3, 1.0)定义椭圆中心的坐标;4是椭圆的宽度,1.0是椭圆的高度。facecolor指定填充色块的颜色,hatch指定椭圆内部的填充图案。axs1.set_xlim((0, 6))和axs1.set_ylim((0, 2.5))定义 x 和 y 轴的限制。 如果没有定义这些限制,将不会绘制补丁,因为它不知道确切地将补丁放置在坐标系中的什么位置。axs2.add_patch(Polygon([[0, 0], [4, 1.1], [6, 2.5], [2, 1.4]], color='b', lw=5, fill=False, hatch='+*'))在axs2上绘制多边形补丁:- 由四点的
x, y坐标指定 fill=False指定补丁内的区域不应填充任何颜色- 与
lw=5类似,color='b'用于多边形的边缘 - 在这里,我们为
hatch使用+*字符
- 由四点的
这是输出图:
使用面向对象的 API 绘制集合
collections是包含许多属性的相似对象的容器。
准备
导入所需的库:
from matplotlib import collections
from IPython.core.display import display
from matplotlib.backends import backend_agg
import numpy as np
操作步骤
以下代码块绘制了一组多边形,这些多边形在给定数量的大小和给定的颜色列表之间循环:
- 定义用于绘制多边形集合的数据:
nsizes = 50 #number of different sizes to be used to plot the items in the collection
npts = 100 # number of items in the collection
r = np.arange(nsizes)
theta = np.linspace(0, 2*np.pi, nsizes)
xx = r * np.sin(theta)
- 绘制集合项的偏移坐标:
rs = np.random.RandomState([125])
xo = rs.randn(npts)
yo = rs.randn(npts)
xyo = list(zip(xo, yo))
- 定义图形大小并将其附加到画布上,并在此图形上定义一个轴域:
figure_manager = backend_agg.new_figure_manager(1, figsize=(8,6))
fig = figure_manager.canvas.figure
axs1 = fig.add_subplot(111)
- 绘制六面正多边形作为集合:
col = collections.RegularPolyCollection(6, sizes=np.fabs(xx) * 20,
offsets=xyo, transOffset=axs1.transData)
axs1.add_collection(col, autolim=True)
- 列出要循环的
colors:
colors = ['b', 'g', 'r', 'c', 'm', 'y', 'k', 'w', 'tab:blue',
'tab:orange', 'tab:green', 'tab:red',
'tab:purple', 'tab:brown', 'tab:pink', 'tab:gray',
'tab:olive', 'tab:cyan']
col.set_color(colors)
- 设置标题和
autoscale_view以调整两个轴上的比例:
axs1.autoscale_view()
axs1.set_title('RegularPolyCollection')
- 在屏幕上显示该图:
display(fig)
工作原理
这是代码的说明:
nsizes和npts指定集合中的大小数和项目数。 如果剩余点的nsizes小于npts,则nsizes将从头开始,循环继续进行。 颜色也是如此。xx = r * np.sin(theta)计算所有nsizes的实际大小。xyo = list(zip(xo, yo))为集合中的每个项目计算 x 和 y 坐标。zip是一个 Python 函数,它从两个或多个列表中获取项目,并创建两个或多个元组。col = collections.RegularPolyCollection()创建多边形的集合。 数字6是多边形的边数,np.fabs()将xx中的所有数字转换为其绝对值(因为大小不能为负),offsets=xy0指定实际坐标,其中多边形将被绘制。axs1.transData是坐标系的内部表示,其解释超出了本书的范围。axs1.add_collection(col, autolim=True)将集合对象连接到定义的轴域axs1,autolim=True确保调整轴限制,以使整个集合都在该范围内。col.set_color(colors)指定要循环显示的颜色列表,以覆盖集合中的所有项目。
输出图如下所示: