Matplotlib 3.0 秘籍(二)
十二、使用axes_grid1工具包
在本章中,我们将学习axes_grid1工具包的功能。 我们将介绍以下秘籍:
- 使用
axisartst和axesgrid1工具包绘制双生轴域 - 使用
AxesDivider绘制散点图和相关的直方图 - 使用
AxesDivider绘制颜色条 - 使用
ImageGrid在网格中用颜色条绘制图像 - 使用
inset_locator放大图像 - 使用
inset_locator绘制插入轴域
介绍
axes_grid1工具包旨在提供一组帮助器类,以在网格中绘制带有颜色条的图像,并根据图像大小正确对齐颜色条。 它可用于放大图像的一部分,绘制插入轴域(类似于图片中的图片),绘制二维图和两个变量,从属轴域和锚定艺术家中每个变量的关联直方图。
使用axisartist和axesgrid1工具箱绘制双生轴域
在第 4 章和“开发可视化来提高发布质量”中,我们学习了如何使用双生轴域方法在图的左右轴域上绘制两个不同的比例尺。 在第 9 章和“开发交互式绘图”中,我们学习了如何在 y 轴域上绘制不同的测量单位,并再次使用twinx方法进行交互式分析 。 在本秘籍中,我们将学习如何使用 Matplotlib twinx主方法以及axisartist和axes_grid1工具包在 y 轴域上绘制多个比例尺。
准备
我们将首先使用 Matplotlib twinx()方法绘制图形。 然后,在“更多”部分中,我们将使用axisartist和axes_grid1工具包再次绘制图形。
您需要使用以下命令导入所需的库:
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator
操作步骤
以下是绘制双生轴域图所需的步骤:
- 定义图形和主轴域(左侧为
ax1, y 轴),如下所示:
fig, ax1 = plt.subplots(1,1)
- 定义双生轴域(右侧为
ax2, y 轴,右侧为ax3,另一 y 轴):
ax2 = ax1.twinx()
ax3 = ax1.twinx()
- 放置
ax3使其不与ax2右侧轴域重叠:
ax3.spines["right"].set_position(("axes", 1.15))
- 准备数据并在主轴域
ax1上绘制产品缺陷条形图:
x = [0, 1, 2, 3, 4, 5]
y = [19, 12, 6, 4, 3, 2]
b = ax1.bar(x, y, label='Number of Defects')
- 在右轴域
ax2上的折线图中准备数据并按百分比绘制累积缺陷:
y = [41, 67, 80, 89, 96, 100]
l, = ax2.plot(x, y, color='g', lw=5, label='Cumulative Defects as %')
- 准备数据并在第二个右轴域
ax3上绘制累积的缺陷计数折线图:
y = [19, 31, 37, 41, 44, 46]
l1, = ax3.plot(x, y, color='m', lw=5, label='Cumulative Defects
Count')
- 定义步长为
2的主定位器,并将其应用于主轴域ax1的 y 轴:
majorLocator = MultipleLocator(2)
ax1.yaxis.set_major_locator(majorLocator)
- 使用以下代码设置 x 和 y 标签以及所有轴域的限制:
ax1.set(xlabel='Defect Reason Codes', ylabel='Number of Defects')
ax2.set(ylabel='Cumulative Defects as %')
ax3.set_ylim(15,50)
ax3.set_ylabel('Cumulative Defects Count', labelpad=10)
- 如下设置主轴域的图例和标题:
graphs = [b, l, l1]
ax1.legend(graphs, [g.get_label() for g in graphs], loc=5)
ax1.set_title('Product Defects - August 2018')
- 设置标签的颜色:
ax1.yaxis.label.set_color(b.patches[0].get_facecolor())
ax2.yaxis.label.set_color(l.get_color())
ax3.yaxis.label.set_color(l1.get_color())
- 设置两个右轴的颜色,如下所示:
ax2.spines["right"].set_edgecolor(l.get_color())
ax3.spines["right"].set_edgecolor(l1.get_color())
- 设置刻度和刻度标签的颜色,如下所示:
ax1.tick_params(axis='y', colors=b.patches[0].get_facecolor())
ax2.tick_params(axis='y', colors=l.get_color())
ax3.tick_params(axis='y', colors=l1.get_color())
- 最后,使用以下命令在屏幕上显示图形:
plt.show()
工作原理
这是前面代码的解释:
-
ax2 = ax1.twinx()和ax3 = ax1.twinx()创建名为ax2和ax3的逻辑轴域,它们共享主轴域(ax1)的 x 轴。 y 轴在右侧。 -
ax3.spines["right"].set_position(("axes", 1.15))将第二个 y 轴向右移动主轴域宽度的 15%。 如果我们不这样做,则ax2和ax3的 y 轴将相互重叠,并在同一轴域上同时显示它们的刻度和刻度标签。 -
x = [0, 1, 2, 3, 4, 5]是产品缺陷代码的列表,y = [19, 12, 6, 4, 3, 2]是缺陷原因代码的列表。 -
b = ax1.bar(x, y, label='Number of Defects')绘制了产品缺陷数量的条形图。 -
y1 = [41, 67, 80, 89, 96, 100]是累积缺陷占总数百分比的列表。 -
l, = ax2.plot(x, y1, color='g', lw=5, label='Cumulative Defects as %')将其绘制为线形图。 -
y2 = [19, 31, 37, 41, 44, 46]是累积缺陷计数的列表。 -
l1, = ax3.plot(x, y2, color='m', lw=5, label='Cumulative Defects Count')将其绘制为线形图。 -
majorLocator = MultipleLocator(2)以2的步长定义定位器,ax1.yaxis.set_major_locator(majorLocator)将定位器应用于主轴域ax1的 y 轴。 -
ax3.set_ylabel('Cumulative Defects Count', labelpad=10)为最右边的轴设置 y 轴标签,而labelpad=10指定该轴与其标签之间的间隙,以使标签不与该轴的刻度标签重叠。 -
ax1.legend(graphs, [g.get_label() for g in graphs], loc=5)绘制图例如下:[g.get_label() for g in graphs]获取在绘制图形时设置的每个图形的标签列表。loc=5指定将图例绘制在轴的右侧。 有关放置图例的更多选项,请参考第 4 章和“开发可视化来提高发布质量”。
-
ax1.yaxis.label.set_color(b.patches[0].get_facecolor())设置主轴域的 y 轴标签的颜色,如下所示:b.patches[0].get_facecolor()获取条形图中第一个条的facecolor值,b.patches[]是另存为色块的条形容器。- 使用此命令,而不是显式设置颜色,我们将使用用于绘制图形的颜色并将其用于 y 轴标签。 始终使用相同的颜色。
-
ax2.yaxis.label.set_color(l.get_color())和ax3.yaxis.label.set_color(l1.get_color())获得线形图l和l1的颜色,并将它们应用于各自的标签。 -
ax2.spines["right"].set_edgecolor(l.get_color())设置右轴的颜色,用于绘制线形图l。 -
ax3.spines["right"].set_edgecolor(l1.get_color())设置第二个右轴的颜色,用于绘制折线图l1。 -
ax1.tick_params(axis='y', colors=b.patches[0].get_facecolor())设置刻度和刻度标签的颜色。
执行上述代码后,您应该在屏幕上看到以下图形:
更多
现在,我们将使用axisartist和axes_grid1工具包绘制相同的图形。 遵循的步骤是相同的,因此在此我们将不描述每个步骤,而是将整个代码列出在一个块中。 此后,我们将解释这两种方法之间的主要区别。
这是使用axisartist和axes_grid1工具包绘制图形的完整代码块:
from mpl_toolkits.axes_grid1 import host_subplot
import mpl_toolkits.axisartist as AA
import matplotlib.pyplot as plt
plt.figure()
ax1 = host_subplot(111, axes_class=AA.Axes)
ax1.axis["top"].toggle(all=False) # switch off ticks and ticklabels for
the top axis
ax2 = ax1.twinx()
ax3 = ax1.twinx()
new_fixed_axis = ax3.get_grid_helper().new_fixed_axis
ax3.axis["right"] = new_fixed_axis(loc="right", axes=ax3, offset=(60,
0))
ax2.axis["right"].toggle(all=True)
ax3.axis["right"].toggle(all=True)
ax1.set_xlabel('Defect Reason Codes')
ax1.set_ylabel('Number of Defects')
ax2.set_ylabel('Cumulative Defects as %')
ax3.set_ylabel('Cumulative Defects Count')
x = [0, 1, 2, 3, 4, 5]
y = [19, 12, 6, 4, 3, 2]
y1 = [41, 67, 80, 89, 96, 100]
y2 = [19, 31, 37, 41, 44, 46]
b = ax1.bar(x, y, label='Number of Defects')
l, = ax2.plot(x, y1, lw=5, label='Cumulative Defects as %', color='b')
l1, = ax3.plot(x, y2, lw=5, label='Cumulative Defects Count',
color='g')
ax3.set_ylim(15, 50)
ax1.legend(loc=5)
ax1.set_title('Product Defects - August 2018')
ax1.axis["left"].label.set_color(b.patches[0].get_facecolor())
ax2.axis["right"].label.set_color(l.get_color())
ax3.axis["right"].label.set_color(l1.get_color())
ax1.axis["left"].major_ticks.set_color(b.patches[0].get_facecolor())
ax2.axis["right"].major_ticks.set_color(l.get_color())
ax3.axis["right"].major_ticks.set_color(l1.get_color())
ax1.axis["left"].major_ticklabels.set_color(b.patches[0].get_facecolor())
ax2.axis["right"].major_ticklabels.set_color(l.get_color())
ax3.axis["right"].major_ticklabels.set_color(l1.get_color())
## setting the color for axis itself is not working in AA
ax2.spines["right"].set_color(l.get_color())
ax3.spines["right"].set_color(l1.get_color())
ax1.axis[:].major_ticks.set_tick_out(True)
ax2.axis[:].major_ticks.set_tick_out(True)
ax3.axis[:].major_ticks.set_tick_out(True)
plt.show()
这是两种方法之间主要区别的解释:
- 而不是使用
plt.subplots(),这里我们使用ax1 = host_subplot(111, axes_class=AA.Axes),它是axes_grid1工具包的辅助函数,它以axisartist作为参数。 这意味着ax1轴域获得host_subplot()和axisartist的属性。 ax2=ax1.twinx()自动为其 y 轴映射ax1的右脊。- 但是,对于
ax3,我们将必须使用以下命令手动创建另一个右轴:new_fixed_axis = ax3.get_grid_helper().new_fixed_axis。ax3.axis["right"] = new_fixed_axis(loc="right", axes=ax3, offset=(60, 0))。offset=(60,0)将轴向右推动60点,0指向顶部。
ax2.axis["right"].toggle(all=True)将ax1右脊的轴标签,刻度和刻度标签设置为可见。ax3.axis["right"].toggle(all=True)将新创建的右轴的轴标签,刻度和刻度标签设置为可见。- 我们为标签,刻度和刻度标签设置各种属性的方式,与我们在第 12 章“使用
axisartist工具包”中了解的方法相同。 - 但是,某些属性无法与原始轴类一起正常工作,因为
axisartist不能继承原始轴类的所有属性。 - 当您使用交互式后端打开该图并放大图形的某些部分时,只有主轴域的 y 限制发生变化,而其他 y 轴的数据则发生变化。 右(从属轴域)与初始设置相同。 如果不使用
axes_grid1和axisartist来绘制先前的图形,情况并非如此,其中所有 y 轴限制都会更改以反映图形的当前部分。
执行前面的代码块后,您应该看到以下图形:
使用AxesDivider绘制散点图和相关的直方图
在本秘籍中,我们将学习如何使用axes_grdi1的AxesDivider类在主轴域上绘制双变量图,并在主轴域的任意两侧绘制两个单变量图。 这有助于可视化两个变量之间的关系,以及同一图中两个变量的分布情况(尽管三个不同的轴域/曲线)。
从技术上讲,在主轴域上绘制的变量和在主轴域两侧上的单变量图可以不同。 您可以从主轴域的四个侧面中选择任意两个侧面以进行单变量图绘制。 但是,通常的做法是绘制在主轴域的顶部和右侧。
在此秘籍中,我们将在带有两个变量的主轴域上绘制散点图,并且在主轴域的顶部和右侧,将为散点图所使用的两个变量分别绘制直方图。
准备
让我们导入所需的库。 应当指出,我们不是直接导入AxesDiveder; 相反,我们正在使用此类的帮助函数make_axes_locatable。 您需要使用以下命令导入库:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
import pandas as pd
操作步骤
以下是绘制图形所涉及的步骤:
- 使用以下命令加载我们先前已经使用的
Iris数据集:
iris = pd.read_csv('iris_dataset.csv', delimiter=',')
iris['species'] = iris['species'].map({"setosa" : 0, "versicolor" :
1, "virginica" : 2})
x, y = iris['sepal_length'], iris['sepal_width']
- 如下定义图形和主轴域:
fig, axmain = plt.subplots(figsize=(8, 6))
- 使用 1 的长宽比在主轴域上绘制散点图
axmain.scatter(x, y)
axmain.set_aspect(1.)
- 定义轴域分割器,以使一个轴域位于主轴域的顶部,另一个轴域位于主轴域的右侧,如下所示:
divider = make_axes_locatable(axmain)
axtop = divider.append_axes("top", size=1.5, pad="15%",
sharex=axmain)
axright = divider.append_axes("right", "100%", 0.1, sharey=axmain)
- 使刻度标签对顶部轴域的 x 轴以及右轴域的 y 轴不可见,以使它们不与主轴域重叠:
axtop.xaxis.set_tick_params(labelbottom=False)
axright.yaxis.set_tick_params(labelleft=False)
- 在上下轴域上绘制直方图:
axtop.hist(x, bins=15)
axright.hist(y, bins=10, orientation='horizontal')
- 设置顶部轴域的
yticks,和右侧轴域的xticks:
axtop.set_yticks([0, 5, 10, 15, 20])
axright.set_xticks([0, 10, 20, 30, 40])
- 如下设置所有轴域的标签和标题:
axmain.set(xlabel='sepal length', ylabel='sepal width', title='iris
scatter plot')
axtop.set_title('sepal length', size=10)
axright.set_title('sepal width', size=10)
- 最后,使用以下命令在屏幕上显示图形:
plt.show()
工作原理
这是前面代码的解释:
- 您已经熟悉了前面的示例的前三个步骤。
divider = make_axes_locatable(axmain)定义轴域分离器。 它实质上是定位给定轴域的边界。axtop = divider.append_axes("top", size=1.5, pad="15%", sharex=axmain)在主轴域上方定义一个新轴域,如下所示:"top"指定要在当前轴域之上绘制的新轴域。size=1.5指定此新轴域的高度为 1.5 英寸,其宽度与主访问宽度相同。pad=15%指定主轴域与顶部新轴域之间的间隙为主轴域高度的 15%。sharex=axmain指定此新轴域应与主轴域共享 x 轴属性,例如轴标签,刻度和刻度标签
axright = divider.append_axes("right", "100%", 0.1, sharey=axmain)在主轴域右侧定义了一个新轴域,如下所示:"right"指定新轴域应绘制在主轴域的右侧。100%指定新轴域的宽度与主轴域的宽度相同。 新轴域的高度也与主轴域的高度相同,因为它们都共享 y 轴。0.1是主轴域和该新轴域之间的填充(以磅为单位)。sharey=axmain指定此新轴域应与主轴域共享 y 轴属性,例如轴标签,刻度和刻度标签。
axtop.xaxis.set_tick_params(labelbottom=False)使 x 轴标签对于上轴域不可见。axright.yaxis.set_tick_params(labelleft=False)使 y 轴标签对于右轴域不可见。axtop.hist(x, bins=15)在具有 15 个桶的顶轴域上绘制直方图。axright.hist(y, bins=10, orientation='horizontal')使用水平条形图而不是默认垂直条形图在带有 10 个桶的右轴域上绘制直方图。- 其余的语句设置所有三个轴域的刻度,标签和标题。
运行代码后,您应该在屏幕上看到以下图形:
使用AxesDivider绘制颜色条
在本秘籍中,我们将学习如何使用AxesDivider绘制图像的颜色条,以确保其与图像正确对齐。 我们已经使用了pyplot.colorbar()很多次,但有时颜色条超出了图像边界。 使用AxesDivider和ImageGrid,我们将不会看到此问题,如本秘籍所示。
我们将在三个轴域上绘制图像–一个使用不带AxesDivider的常规pyplot.colorbar(); 第二个使用AxesDivider和右侧的垂直颜色条; 第三个再次使用AxesDivider,但这一次在图像顶部带有水平色条。
准备
您需要使用以下命令导入所需的库:
import matplotlib.pyplot as plt
from matplotlib.pyplot import imshow
from mpl_toolkits.axes_grid1 import make_axes_locatable
import numpy as np
import pandas as pd
操作步骤
以下是使用颜色条绘制图像所涉及的步骤:
- 将数据集加载到
winequality.csv上,如下所示:
wine_quality = pd.read_csv('winequality.csv', delimiter=';')
corr_wine = wine_quality.corr()
- 使用以下命令定义该图:
fig = plt.figure(1, (16., 6.))
- 定义第一个子图,绘制图像和颜色条,并使用以下代码设置 x 和 y 刻度。
plt.subplot(131)
plt.imshow(corr_wine, cmap='plasma')
plt.colorbar()
plt.xticks(range(len(corr_wine)),corr_wine.columns, rotation=75)
plt.yticks(range(len(corr_wine)),corr_wine.columns)
- 使用以下代码,定义第二个子图,绘制图像,定义
AxesDivider,在右侧绘制颜色条,然后设置 x 和 y 刻度。
ax2 = plt.subplot(132)
im1 = ax2.imshow(corr_wine, cmap='Blues')
ax2_divider = make_axes_locatable(ax2)
cax1 = ax2_divider.append_axes("right", size="7%", pad=0.03)
plt.colorbar(im1, cax=cax1)
ax2.set_xticks(range(len(corr_wine)))
ax2.set_xticklabels(corr_wine.columns, rotation=75)
ax2.set(yticks=range(len(corr_wine)), yticklabels=corr_wine.columns)
- 定义第三个子图,绘制图像,定义
AxesDivider,在顶部绘制水平色条,然后按如下所示设置 x 和 y 刻度。
ax3 = plt.subplot(133)
im2 = ax3.imshow(corr_wine)
ax3_divider = make_axes_locatable(ax3)
cax2 = ax3_divider.append_axes("top", size="7%", pad="2%")
cb2 = plt.colorbar(im2, cax=cax2, orientation="horizontal")
cax2.xaxis.set_ticks_position("top")
ax3.set_xticks(range(len(corr_wine)))
ax3.set_xticklabels(corr_wine.columns, rotation=75)
ax3.set(yticks=range(len(corr_wine)), yticklabels=corr_wine.columns)
- 使用以下命令调整绘图之间的间隔:
plt.tight_layout(w_pad=-1)
7.最后,使用以下命令在屏幕上显示图形:
plt.show()
工作原理
这是前面代码的解释:
fig = plt.figure(1, (16., 6.))将图 1 定义为16 x 6英寸。plt.subplot(131)定义1 x 3网格上的第一个轴域。plt.imshow(corr_wine, cmap='plasma')使用'plasma'颜色表绘制相关图。plt.colorbar()在其右侧绘制图像的颜色条。plt.xticks(range(len(corr_wine)),corr_wine.columns, rotation=75)在75度的倾斜度上绘制 x 轴刻度和带有属性名称的刻度标签。plt.yticks(range(len(corr_wine)),corr_wine.columns)绘制 y 轴刻度和刻度标签,没有任何旋转。ax2 = plt.subplot(132)在1 x 3的网格上定义第二个轴域。im1 = ax2.imshow(corr_wine, cmap='Blues')使用'Blues'颜色表绘制相关图。ax2_divider = make_axes_locatable(ax2)为第二个轴域定义AxesDivider函数。cax1 = ax2_divider.append_axes("right", size="7%", pad=0.03)使用AxesDivider定义了颜色条的新轴域。"right"指定将新轴域放置在ax2的右侧。size="7"指定新轴域的宽度应为ax2宽度的 7%。pad=0.03指定ax2轴域和颜色条轴域之间的间隙应为ax2宽度的 3%。plt.colorbar(im1, cax=cax1)绘制ax2右侧的颜色条,并带有给定的图像和颜色条轴域。ax2.set_xticks(range(len(corr_wine)))将 x 轴刻度设置为输入数据中我们具有的属性数。ax2.set_xticklabels(corr_wine.columns, rotation=75)设置带有属性名称和75倾斜度的刻度标签。ax2.set(yticks=range(len(corr_wine)), yticklabels=corr_wine.columns)设置 y 轴刻度和刻度标签,不旋转。ax3 = plt.subplot(133)在1 x 3的网格上定义第三个轴域。- 其余步骤与前面介绍的第二个图完全相同,除了颜色条以水平方向而不是默认垂直方向绘制在图像顶部。
plt.tight_layout(w_pad=-1)调整绘图之间的间隔,以确保没有重叠。 负w_pad值用于减小tight_layout()使用的默认间隙。
运行上述代码后,您应该在屏幕上看到以下图形。 应该注意的是,在第一个图中,颜色条超出了图像的高度,而在第二个和第三个图中,它与图像的高度或宽度完全匹配,这是使用AxesDivider的优点:
使用ImageGrid在网格中使用颜色条绘制图像
在第 3 章,“绘制多个图形,子图形和图形”和第 6 章,“绘制高级功能”的过程中,我们学习了如何在网格上绘制具有多个网格选项的多个图。 当您尝试使用带有这些选项的网格上的颜色条来绘制图像时,颜色条对齐可能不是我们想要的方式。axes_grid1工具包的ImageGrid辅助函数可在网格中以正确对齐方式绘制带有颜色条的图像。 我们将在本秘籍中学习如何使用这些功能。
我们将在三个不同的图中连续绘制相同的相关图,但是使用网格的不同特征来演示大多数(如果不是全部)可用特征。
准备
您需要使用以下命令导入所需的库:
import matplotlib.pyplot as plt
from matplotlib.pyplot import imread, imshow
from mpl_toolkits.axes_grid1 import ImageGrid
import pandas as pd
操作步骤
以下是绘制所需图形所涉及的步骤:
- 加载数据并创建具有相同相关矩阵的四个图像的列表,如下所示:
wine_quality = pd.read_csv('winequality.csv', delimiter=';')
corr_wine = wine_quality.corr()
images = []
images.append(corr_wine)
images.append(corr_wine)
images.append(corr_wine)
images.append(corr_wine)
- 定义大小为
12 x 8英寸的图形:
fig = plt.figure(1, (12, 8.))
- 定义要在第一个轴域上绘制的
2 x 2网格:
grid1 = ImageGrid(fig, 131, nrows_ncols=(2, 2), axes_pad=0.0,
label_mode="1")
- 如下设置 x 和 y 刻度和刻度标签:
grid1.axes_llc.set_xticks(range(len(corr_wine)))
grid1.axes_llc.set_xticklabels(corr_wine.columns, rotation=90)
grid1.axes_llc.set(yticks=range(len(corr_wine)),
yticklabels=corr_wine.columns)
- 在先前定义的
2 x 2网格上绘制具有相同相关矩阵的四张图像,没有颜色条,:
for i in range(4):
gd = grid1[i].imshow(images[i], cmap='coolwarm')
- 定义另一个要在第二个轴域上绘制的
2 x 2网格:
grid2 = ImageGrid(fig, 132, nrows_ncols=(2, 2), axes_pad=0.1, label_mode="L", cbar_location="top",
cbar_mode="single")
- 在先前定义的
2 x 2网格上,用相同的相关矩阵在上绘制四个图像:
for i in range(4):
im = grid2[i].imshow(images[i])
grid2.cbar_axes[0].colorbar(im)
- 定义要在第三个轴域上绘制的第三个
2 x 2网格:
grid3 = ImageGrid(fig, 133, nrows_ncols=(2, 2), axes_pad=(0.5, 0.3),
abel_mode="0",
cbar_location="right", cbar_mode="each",
cbar_size="10%", cbar_pad="3%")
- 在先前定义的
2 x 2网格上绘制具有相同或相关矩阵的四个图像:
limits = ((-1, 1), (-1, 0), (0, 1.), (-0.5, 0.5))
for i in range(4):
im = grid3[i].imshow(images[i], interpolation="nearest",
vmin=limits[i][0], vmax=limits[i][1])
grid3.cbar_axes[i].colorbar(im)
grid3.cbar_axes[i].set_yticks((limits[i][0], limits[i][1]))
- 最后,使用以下命令在屏幕上显示该图:
plt.show()
工作原理
这是前面代码的解释:
images = []用空白初始化图像列表。images.append(corr_wine)将corr_wine相关矩阵附加到图像列表。 我们重复四次以创建要在2 x 2网格上绘制的四个图像的列表。grid1 = ImageGrid(fig, 131, nrows_ncols=(2, 2), axes_pad=0.0, label_mode="1")如下定义图像网格:fig指定要在其上绘制网格的图形。131指定它是一个1 x 3的网格,并且这是第一个网格。nrows_ncols=(2,2)将网格格式指定为2 x 2。axes_pad=0.0指定图像之间的间隔为零。label_mode="1"指定应仅为网格的左下角图像打印刻度标签和轴标签。
grid1.axes_llc.set_xticks(range(len(corr_wine)))设置 x 轴上的刻度线,其数量与相关矩阵中的变量数量一样多。grid1.axes_llc.set_xticklabels(corr_wine.columns, rotation=90)在 x 轴上以90度倾斜度打印带有变量名的刻度标签。grid1.axes_llc.set(yticks=range(len(corr_wine)), yticklabels=corr_wine.columns)使用相同的变量名称为 y 轴打印刻度和刻度标签,无需旋转。for i in range(4):是for循环,可在四个网格中一张一张地绘制图像:gd = grid1[i].imshow(images[i], cmap='coolwarm')使用coolwarm色彩图绘制图像。
grid2 = ImageGrid()使用以下参数定义第二个图像网格:fig指定要绘制此网格的图形。132指定它是另一个1 x 3网格中的第二个网格。nrows_ncols=(2,2)将网格格式指定为2 x 2。axes_pad=0.1将图像之间的间隙指定为 0.1 英寸。label_mode="L"指定是要为左右图像绘制的标签,形成"L"形状。cbar_location="top"指定颜色条应绘制在图像顶部。cbar_mode="single"指定只能在网格顶部绘制一个颜色条。
for i in range(4):是用于在四个网格上一一绘制图像的for循环:im = grid2[i].imshow(images[i], cmap='ocean')使用'ocean'颜色表绘制图像。
grid2.cbar_axes[0].colorbar(im)打印颜色条。grid3 = ImageGrid()定义第三个图像网格,其参数如下:fig指定要绘制此网格的图形。133指定它是另一个1 x 3网格中的第三个网格。nrows_ncols=(2,2)将网格格式指定为2 x 2。axes_pad=(0.5,0.3)将图像之间的间距指定为水平0.5英寸和垂直0.3英寸。label_mode="0",指定要为所有图像绘制标签。cbar_location="right"指定应在图像的右侧绘制颜色条。cbar_mode="each"指定应在网格中每个图像的右侧绘制颜色条。cbar_size="10%"指定彩条宽度应为图像轴域宽度的10%。cbar_pad="3%"指定彩条和图像之间的距离为图像轴域宽度的 3%。limits = ((-1, 1), (-1, 0), (0, 1.), (-0.5, 0.5))指定要应用于四个图像的每个颜色条的下限和上限,而不是绘制 -1 至 +1 的整个范围。
for i in range(4):是用于在四个网格中一一绘制图像的for循环:im = grid3[i].imshow(images[i], interpolation="nearest", vmin=limits[i][0], vmax=limits[i][1], cmap='ocean')使用'ocean'色彩图绘制图像。interpolation="nearest"指定值超出指定限制的单元格将填充这些限制内的最近单元格值。vmin=limits[i][0]指定给定i图像(元组的第一项)的下限。vmax=limits[i][1]指定给定i图像(元组的第二个条目)的上限。grid3.cbar_axes[i].colorbar(im)打印颜色条。grid3.cbar_axes[i].set_yticks((limits[i][0], limits[i][1]))使用给定的限制设置 y 轴的刻度和刻度标签。
执行上述代码后,您应该在屏幕上看到以下图形:
使用inset_locator放大图像
在第 6 章“带有高级功能的绘图”中,我们学习了如何使用 Matplotlib 的面向对象接口在主轴域内绘制插入轴域。 在本秘籍和下一篇秘籍中,我们将学习如何使用axes_grid1工具包的inset_locator助手函数创建插入轴域并绘制图像和其他图形。
在本秘籍中,我们将学习如何放大图像的一部分并将其显示在相同主轴域的插入轴域上。
我们将在两个轴域上绘制图像,并在每个图中放大图像的不同部分。
准备
您需要使用以下命令导入所需的库:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from mpl_toolkits.axes_grid1.inset_locator import zoomed_inset_axes
from mpl_toolkits.axes_grid1.inset_locator import mark_inset
操作步骤
这是绘制图形的必要步骤:
- 如下定义图形和两个轴域:
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=[8, 4])
- 使用以下命令加载
winequality数据并计算相关矩阵:
wine_quality = pd.read_csv('winequality.csv', delimiter=';')
corr_wine = wine_quality.corr()
- 创建一个带有零的扩展图像,并将相关矩阵插入其中:
extended_image = np.zeros([100, 100], dtype="d")
ny, nx = corr_wine.shape
extended_image[25:25 + ny, 25:25 + nx] = corr_wine
- 绘制具有给定范围的扩展图像,即 x 和 y 限制,如下所示:
extent = [-2, 2, -3, 1]
ax1.imshow(extended_image, extent=extent, interpolation="nearest",
origin="lower")
- 定义插入轴域,如下所示:
axins1 = zoomed_inset_axes(ax1, 3, loc=1)
- 在插入轴域上绘制扩展图像:
axins1.imshow(extended_image, extent=extent,
interpolation="nearest", origin="lower")
- 设置 x 和 y 轴的插入轴域数据限制,并指定要放大的相关矩阵部分:
axins1.set_xlim(-1.0, -0.5)
axins1.set_ylim(-2.0, -1.5)
- 使用以下给定值设置刻度线:
axins1.xaxis.get_major_locator().set_params(nbins=8)
axins1.yaxis.get_major_locator().set_params(nbins=8)
- 将插入轴域的刻度标签设置为在 x 和 y 轴上均不可见:
plt.xticks(visible=False)
plt.yticks(visible=False)
- 在选定要缩放的部分周围标记一个边界框,并使用线条将其与缩放的插入轴域连接:
mark_inset(ax1, axins1, loc1=2, loc2=4, fc="none", ec="b")
- 对第二个轴域重复执行步骤 4 至步骤 8 ,这将显示放大的图像较小的部分:
ax2.imshow(extended_image, extent=extent, interpolation="nearest",
origin="lower")
axins2 = zoomed_inset_axes(ax2, 3, loc=1) # zoom = 3
axins2.imshow(extended_image, extent=extent,
interpolation="nearest", origin="lower")
axins2.set_xlim(-1.0, -0.75)
axins2.set_ylim(-2.0, -1.75)
axins2.yaxis.get_major_locator().set_params(nbins=8)
axins2.xaxis.get_major_locator().set_params(nbins=8)
plt.xticks(visible=False)
plt.yticks(visible=False)
mark_inset(ax2, axins2, loc1=2, loc2=4, fc="none", ec="m")
- 最后,使用以下命令在屏幕上显示图:
plt.show()
工作原理
这是前面代码的解释:
extended_image = np.zeros([100, 100], dtype="d")创建一个用零填充的100 x 100NumPy 数组,并将数据类型指定为双精度浮点数。nx, ny = corr_wine.shape将相关矩阵的形状分为nx和ny。extended_image[25:25 + nx, 25:25 + ny] = corr_wine将相关矩阵嵌入在(25, 25)位置的100 x 100零矩阵内,用corr_wine的值替换零。extent = [-2, 2, -3, 1]指定主轴域的 x 坐标上的数据限制为(-2, 3)和 y 为(-3, 1)。 有关更多详细信息,请参考第 6 章,“带有高级功能的绘图”,“起源和范围”中的秘籍。ax1.imshow(extended_image, extent=extent, interpolation="nearest", origin="lower")在主轴域ax1上绘制扩展图像。axins1 = zoomed_inset_axes(ax1, 3, loc=1)定义插入轴域如下:ax1是要在其上创建插入轴域的轴域。3指定插入轴域数据比例是主轴域的三倍,因此对于 x 和 y 轴,主轴域上的一个单位缩放到插入轴域上的三个单位。loc=1指定将插入轴域放置在主轴域的右上角。
axins1.imshow(extended_image, extent=extent, interpolation="nearest", origin="lower")在插入轴域上绘制相同的扩展图像,并使用与主轴域相同的参数。axins1.set_xlim(-1.0, -0.5)和axins1.set_ylim(-2.0, -1.5)指定主轴域上要放大的图像部分。axins1.xaxis.get_major_locator().set_params(nbins=8)和axins1.yaxis.get_major_locator().set_params(nbins=8)定义插入轴域的 x 和 y 轴上的刻度数。plt.xticks(visible=False)和plt.yticks(visible=False)使插入标签的 x 和 y 轴均不可见刻度标签。mark_inset(ax1, axins1, loc1=2, loc2=4, fc="none", ec="b")围绕要缩放的图像以及缩放的图像本身绘制边界,然后将它们连接到线条,如下所示:ax1是主轴域的引用。axins1的插入轴域的引用。loc1和loc2指定要连接图像的哪些角;2指左上角,4指右下角。fc="none"指定不填充连接两个图像的线之间的区域。ec="b"指定连接图像的线应为蓝色。
- 我们的第二个图与第一个图完全相同,只是要放大的图像部分小于第一个图。
axins2.set_xlim(-1.0, -0.75)和axins2.set_ylim(-2.0, -1.75)指定第二幅图要放大的主图像区域。
执行上述代码后,您应该在屏幕上看到以下图形:
使用inset_locator绘制插入轴域
在本秘籍中,我们将学习在主轴域上绘制散点图,并在两个插入轴域上创建两个变量中每个变量的直方图。 我们将使用熟悉的Iris数据集来执行此操作。
准备
您需要使用以下命令导入所需的库:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
操作步骤
这是绘制图形的分步方法:
- 加载
Iris数据集,并使用sepal_length和sepal_width变量映射 x 和 y 坐标:
iris = pd.read_csv('iris_dataset.csv', delimiter=',')
iris['species'] = iris['species'].map({"setosa" : 0, "versicolor" :
1, "virginica" : 2})
x, y = iris['sepal_length'], iris['sepal_width']
- 如下定义图形和主轴域:
plt.figure(1, (8., 6.))
ax = plt.subplot(111)
- 使用右侧的颜色条绘制散点图:
im = ax.scatter(x, y, c=iris.petal_length, s=100*iris.petal_width, cmap='viridis', alpha=0.7)
plt.colorbar(im)
- 如下定义插入轴域 1 的属性:
inset_ax1 = inset_axes(ax, width="40%", height=1., loc=4)
- 在插入轴域 1 上绘制
sepal_length直方图:
inset_ax1.hist(iris.sepal_length)
- 设置插入轴域的标题和标签,如下所示:
inset_ax1.set_title('sepal length', size=10, pad=20)
inset_ax1.axis["bottom"].toggle(all=False)
inset_ax1.axis["top"].toggle(all=True)
inset_ax1.xaxis.get_major_locator().set_params(nbins=5)
inset_ax1.yaxis.get_major_locator().set_params(nbins=10)
- 如下定义插入轴域 2 的属性:
inset_ax2 = inset_axes(ax, width=1.5, height="25%", loc=2)
8.在插入轴域 2 上绘制sepal_width直方图:
inset_ax2.hist(iris.sepal_width)
- 设置插入轴域的标题和标签,如下所示:
inset_ax2.set_title('sepal width', size=10)
inset_ax2.axis["left"].toggle(all=False)
inset_ax2.axis["right"].toggle(all=True)
inset_ax2.xaxis.get_major_locator().set_params(nbins=6)
inset_ax2.yaxis.get_major_locator().set_params(nbins=10)
- 设置主轴域的标题和标签,如下所示:
ax.set(xlabel='sepal length', ylabel='sepal width')
ax.set_title('iris plot', size=20, color='g')
- 最后,使用以下命令在屏幕上显示图:
plt.show()
工作原理
这是前面代码的解释:
im = ax.scatter(x, y, c=iris.petal_length, s=100*iris.petal_width, cmap='viridis', alpha=0.7)在主轴域上绘制散点图,如下所示:x和y是要绘制的sepal_length和sepal_width变量。c=iris.petal_length指定点的颜色应根据其petal_length值。s=100*iris.petal_width指定散点图上的点的大小应根据其petal_width值乘以100来确定。cmap='viridis'指定要使用的颜色表。alpha=0.7指定绘图上点的透明度级别。
plt.colorbar(im)在主轴域的右侧绘制颜色条。inset_ax1 = inset_axes(ax, width="40%", height=1., loc=4)定义插入轴域 1 的属性,如下所示:ax是要放置插入轴域的主轴域。width="40%"指定插入轴域的宽度应为主轴域宽度的40%。height=1.指定插入轴域的高度应为 1 英寸。loc=4指定将插入轴域放置在主轴域的右下角。
inset_ax1.hist(iris.sepal_length)绘制sepal_length变量的直方图。inset_ax1.set_title('sepal legth', size=10, pad=20)打印大小为10点的插入轴域标题,并将其定位在顶部轴域上方20点,以使刻度标签和标题不重叠。inset_ax1.axis["bottom"].toggle(all=False)将底部轴的轴标签,刻度和刻度标签设置为不可见。inset_ax1.axis["top"].toggle(all=True)将顶部轴的轴标签,刻度和刻度标签设置为可见。inset_ax1.xaxis.get_major_locator().set_params(nbins=5)指定 x 轴上的刻度数。inset_ax1.yaxis.get_major_locator().set_params(nbins=10)指定 y 轴上的刻度数。inset_ax2 = inset_axes(ax, width=1.5, height="25%", loc=2)定义第二插入轴域如下:width=1.5将插入轴域的宽度指定为1.5英寸。height="25%"指定插入轴域的高度为主轴域高度的25%。loc=2指定将插入轴域放置在主轴域的左上角。
ax.set(xlabel='sepal length', ylabel='sepal width')设置主轴域的 x 和 y 轴标签。ax.set_title('iris plot', size=20, color='g')用20点的大小和绿色设置图形的标题。
执行上述代码后,您应该在屏幕上看到以下图形:
十三、使用 Cartopy 工具包绘制地理地图
在本章中,我们将介绍以下秘籍:
- 绘制基本地图特征
- 绘制投影
- 使用网格线和标签
- 在地图上绘制位置
- 绘制具有政治边界的国家地图
- 使用 GeoPandas 和 Cartopy 绘制国家地图
- 绘制世界人口稠密的地方
- 绘制人口前五名和后五名的国家
- 绘制全球温度
- 绘制时区
- 绘制动画地图
介绍
Cartopy 是用于在 Matplotlib 上绘制地理地图的第三方工具包。 预计到 2020 年,Cartopy 将取代 Basemap。Cartopy 具有多种功能,可满足许多不同的用户群体。 在这里,我们将尝试介绍企业中通常使用的大多数功能。
地理地图以经度和纬度绘制,均以度为单位。 经度绘制在 x 轴上,并且从西到 180 度(-180)到东到 180 度(180)变化。 纬度绘制在 y 轴上,并且从向南 90 度(-90)到向北 90 度(90)变化。 地图上的位置以其经度和纬度值标识。
绘制基本地图特征
在本秘籍中,我们将学习 Cartopy 提供的用于绘制地图的基本功能。 该秘籍将涵盖国家边界,沿海地区与陆地,陆地区域,海洋,河流和湖泊的边界等特征。 它还将介绍如何提供背景图像以实现更好的可视化效果。
准备
您需要使用以下命令导入所需的库:
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
操作步骤
以下是绘制基本地图所涉及的步骤:
- 如下定义图形和轴域:
fig = plt.figure(figsize=(12,8))
ax = fig.add_subplot(1, 1, 1, projection=ccrs.PlateCarree())
- 使用以下命令设置范围和背景图像:
ax.set_global()
ax.stock_img()
- 添加如下所需的特征以在地图中绘制:
ax.add_feature(cfeature.LAND, color='wheat')
ax.add_feature(cfeature.OCEAN, color='skyblue')
ax.add_feature(cfeature.COASTLINE, linestyle='-',lw=3)
ax.add_feature(cfeature.BORDERS, linestyle=':')
ax.add_feature(cfeature.LAKES, alpha=0.5, color='y')
ax.add_feature(cfeature.RIVERS, color='blue')
ax.tissot(facecolor='orange', alpha=0.4) # Tissot's indicatrix in cartography
- 设置标题和标签,如下所示:
ax.set_title('Cartopy Map Features - Demo', size=20, weight='bold', color='g')
ax.text(0.5, -0.06, 'Longitude', va='bottom', ha='center', size=15, color='r',
rotation='horizontal', rotation_mode='anchor', transform=ax.transAxes)
ax.text(-0.02, 0.55, 'Latitude', va='bottom', ha='center', size=15, color='b',
rotation='vertical', rotation_mode='anchor', transform=ax.transAxes)
- 最后,使用以下命令在屏幕上显示地图:
plt.show()
工作原理
这是前面代码的解释:
-
import cartopy.crs as ccrs导入负责设置参考坐标系的包。 -
import cartopy.feature as cfeature导入用于绘制各种特征(如陆地,海洋,河流和湖泊)的包装。 -
ax = fig.add_subplot(1, 1, 1, projection=ccrs.PlateCarree())定义要在其上绘制地图的轴域,如下所示:(1,1,1)指定它是1 x 1网格中的第一个轴域,这实际上意味着它是整个图形中的唯一图。projection=ccrs.PlateCarree()指定用于绘制地图的坐标参考系统。 Cartopy 提供了许多这样的投影(参考坐标系)。 在下一秘籍中,我们将看到很多。- 投影仅提供地图的轮廓,因此根据我们要绘制的内容,我们可以添加各种预定义的特征,然后绘制我们感兴趣的数据。
-
ax.set_global()指定坐标系的限制由整个地球形成,这恰好是默认设置。 通过覆盖此全局设置,我们可以设置较小的限制来绘制特定的关注区域。 我们将在后续秘籍中学习如何执行此操作。 -
ax.stock_img()在背景上绘制默认图像,以提供更好的可视化效果。 也可以用我们自己的图像覆盖它。 -
ax.add_feature(cfeature.LAND, color='wheat')绘制使用wheat颜色设置标记为陆地的区域。 -
ax.add_feature(cfeature.OCEAN, color='skyblue')使用skyblue颜色设置绘制海洋。 -
ax.add_feature(cfeature.COASTLINE, linestyle='-',lw=3)绘制了沿沿海地区将土地和水分离的线,线宽为3点,虚线样式。 -
ax.add_feature(cfeature.BORDERS, linestyle=':')使用冒号线型绘制国家边界。 -
ax.add_feature(cfeature.LAKES, alpha=0.5, color='y')使用yellow颜色设置绘制湖泊。 -
ax.add_feature(cfeature.RIVERS, color='blue')使用颜色blue绘制河流。 -
ax.tissot(facecolor='orange', alpha=0.4)绘制天梭的底线。 -
ax.set_title('Cartopy Map Features - Demo', size=20, weight='bold', color='g')打印带有各种文本相关属性的标题。 -
ax.text()用于打印 x 和 y 标签。 常规的ax.set_xlabel和ax.set_ylabel命令在这里不起作用,因为ax.gridlines()函数具有轴域控件,该函数也没有用于绘制 x 和 y 轴标签的预定义方法。
运行上述代码后,您应该在屏幕上看到以下地图:
绘制投影
如先前的秘籍中所述,投影是在其中绘制地图的坐标参考系统。 Cartopy 提供了许多不同的投影,在本秘籍中,我们将绘制九个带有默认参数的投影,以演示它们的外观。 可用投影的完整列表可以在这个页面中找到。
准备
您需要使用以下命令导入所需的库:
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
操作步骤
以下是绘制九种不同投影所涉及的步骤:
- 定义图:
fig = plt.figure(figsize=(12,9))
- 将
3 x 3网格中的轴域一一定义为子图,并为每个图使用不同的投影,如下所示:
ax1 = fig.add_subplot(331, projection=ccrs.PlateCarree())
- 为每个图设置默认的背景图像:
ax1.stock_img()
- 打印图的标题,如下所示:
ax1.set_title('PlateCarree', color='green')
- 然后,对我们的九种不同投影重复步骤 1 至步骤 4。 请参阅此处的示例:
ax2 = fig.add_subplot(332, projection=ccrs.Mercator())
ax2.stock_img()
ax2.set_title('Mercator', color='green')
ax3 = fig.add_subplot(333, projection=ccrs.LambertCylindrical())
ax3.stock_img()
ax3.set_title('LambertCylindrical', color='green')
ax4 = fig.add_subplot(334, projection=ccrs.Robinson())
ax4.stock_img()
ax4.set_title('Robinson', color='green')
ax5 = fig.add_subplot(335, projection=ccrs.Mollweide())
ax5.stock_img()
ax5.set_title('Mollweide', color='green')
ax6 = fig.add_subplot(336, projection=ccrs.Orthographic())
ax6.stock_img()
ax6.set_title('Orthographic', color='green')
ax7 = fig.add_subplot(337, projection=ccrs.Sinusoidal())
ax7.stock_img()
ax7.set_title('Sinusoidal', color='green')
ax8 = fig.add_subplot(338, projection=ccrs.RotatedPole())
ax8.stock_img()
ax8.set_title('RotatedPole', color='green')
ax9 = fig.add_subplot(339, projection=ccrs.InterruptedGoodeHomolosine())
ax9.stock_img()
ax9.set_title('InterruptedGoodeHomolosine', color='green')
- 为整个图形打印一个超级标题:
fig.suptitle("Cartopy Projections - Demo", size=20, weight='bold', color='blue')
- 最后,使用以下命令在屏幕上显示整个图形:
plt.show()
工作原理
这是前面代码的解释:
ax1 = fig.add_subplot(331, projection=ccrs.PlateCarree())在9个轴域(曲线)的3 x 3网格上定义了第一个轴域,并对轴域使用PlateCarree投影,如以下屏幕截图所示ax1.stock_img()将默认图像绘制为地图的背景。- 对所有九个预测重复前两个步骤
- 由于这是可用的示例投影的演示,因此我们不会添加任何预定义功能或任何其他用户定义的地图
执行上述代码后,您应该在屏幕上看到以下图表:
使用网格线和标签
在本秘籍中,我们将学习如何绘制网格线以及如何管理刻度线和刻度线标签。 Cartopy 具有预定义的gridlines()函数来管理这些功能,该功能具有许多助手函数,可根据需要格式化标签。
我们将绘制四个图表来演示默认选项,以及当我们要以特定的自定义方式绘制标签时可能的自定义程度。
准备
您需要使用以下命令导入所需的库:
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter
import cartopy.crs as ccrs
from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER
操作步骤
以下是使用各种选项设置刻度和标签格式来绘制四个图表的步骤:
- 在第一个图上用
PlateCarree投影定义图形和轴域,如下所示:
fig = plt.figure(figsize=(12,8))
ax1 = fig.add_subplot(221, projection=ccrs.PlateCarree())
- 应用默认图像作为背景,并将海岸线特征添加到绘图中:
ax1.stock_img()
ax1.coastlines()
- 定义
gridlines()函数,如下所示:
gl1 = ax1.gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
linewidth=2, color='gray', alpha=0.5,
linestyle='--')
- 关闭上轴和右轴标签:
gl1.xlabels_top = False
gl1.ylabels_right = False
- 定义 x 和 y 轴标签样式,如下所示:
gl1.xlabel_style = {'size': 10, 'color': 'indigo', 'weight': 'bold'}
gl1.ylabel_style = {'size': 10, 'color':'darkblue','weight': 'bold'}
- 打印标题和 x 和 y 标签,并为第一张图使用默认的刻度和刻度标签,如下所示:
ax1.set_title('PlateCarree - Default Ticks', color='green', size=15)
ax1.text(0.5, -0.15, 'Longitude', va='bottom', ha='center',
size=10, color='r', rotation='horizontal',
rotation_mode='anchor', transform=ax1.transAxes)
ax1.text(-0.08, 0.55, 'Latitude', va='bottom', ha='center',
size=10, color='b', rotation='vertical',
rotation_mode='anchor', transform=ax1.transAxes)
- 使用
Mercator投影定义第二个绘图的轴域。 应用背景图像,并像以前一样添加海岸线特征:
ax2 = fig.add_subplot(222, projection=ccrs.Mercator())
ax2.stock_img()
ax2.coastlines()
- 定义
gridlines()函数,如下所示:
gl2 = ax2.gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
linewidth=2, color='gray', alpha=0.5,
linestyle='--')
- 关闭下轴和左轴标签:
gl2.xlabels_bottom = False
gl2.ylabels_left = False
- 定义 x 和 y 轴标签的格式化器:
gl2.xformatter = LONGITUDE_FORMATTER
gl2.yformatter = LATITUDE_FORMATTER
- 定义标签样式,然后为第二个图表打印标题和标签:
gl2.xlabel_style = {'size': 10, 'color': 'indigo', 'weight': 'bold'}
gl2.ylabel_style = {'size': 10, 'color': 'darkblue', 'weight':
'bold'}
ax2.set_title('Mercator - Formatted Ticks', color='green', size=15,
pad=30)
ax2.text(0.5, -0.1, 'Longitude', va='bottom', ha='center',
size=10, color='r', rotation='horizontal',
rotation_mode='anchor', transform=ax2.transAxes)
ax2.text(-0.05, 0.55, 'Latitude', va='bottom', ha='center',
size=10, color='b', rotation='vertical',
rotation_mode='anchor', transform=ax2.transAxes)
- 对于第三幅图,我们将执行以下操作: * 对 x 轴使用固定的刻度位置 * 关闭 x 轴的网格线 * 关闭上轴和左轴的标签
其余功能与前两个图中的相同。 有关示例,请参见以下代码块:
ax3 = fig.add_subplot(223, projection=ccrs.Mercator())
ax3.stock_img()
ax3.coastlines()
gl3 = ax3.gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
linewidth=2, color='gray', alpha=0.5, linestyle='--')
gl3.xlabels_top = False
gl3.ylabels_left = False
gl3.xlines = False
gl3.xlocator = mticker.FixedLocator([-180, -45, 0, 45, 180])
gl3.xformatter = LONGITUDE_FORMATTER
gl3.yformatter = LATITUDE_FORMATTER
gl3.xlabel_style = {'size': 10, 'color': 'indigo', 'weight': 'bold'}
gl3.ylabel_style = {'size': 10, 'color': 'darkblue', 'weight': 'bold'}
ax3.set_title('Mercator - Xticks at fixed locations', color='green', size=15)
- 在第四幅图中,我们将完全使用完全自定义的标签和格式选项,而根本不使用
gridlines()函数,如下所示:
ax4 = fig.add_subplot(2, 2, 4, projection=ccrs.PlateCarree(central_longitude=180))
ax4.set_global()
ax4.stock_img()
ax4.coastlines()
ax4.set_xticks([0, 60, 120, 180, 240, 300, 360], crs=ccrs.PlateCarree())
ax4.set_yticks([-90, -60, -30, 0, 30, 60, 90], crs=ccrs.PlateCarree())
lon_formatter = LongitudeFormatter(zero_direction_label=True,
number_format='.1f', degree_symbol='')
lat_formatter = LatitudeFormatter(number_format='.1f')
ax4.xaxis.set_major_formatter(lon_formatter)
ax4.yaxis.set_major_formatter(lat_formatter)
[i.set_color("indigo") for i in ax4.get_xticklabels()]
[i.set_weight("bold") for i in ax4.get_xticklabels()]
[i.set_color("darkblue") for i in ax4.get_yticklabels()]
[i.set_weight("bold") for i in ax4.get_yticklabels()]
ax4.set_title('PlateCarree - Xticks & Yticks at fixed locations',
color='green', size=15)
- 最后,使用以下命令在屏幕上显示该图:
plt.show()
工作原理
这是前面代码的解释:
gl1 = ax1.gridlines(crs=ccrs.PlateCarree(), draw_labels=True, linewidth=2, color='gray', alpha=0.5, linestyle='--')定义要绘制的网格线的格式:ccrs.PlateCarree()指定要使用的参考坐标系(即投影)。 在这种情况下,我们将使用PlateCarree投影。draw_labels=True指定要绘制与网格线对齐的刻度和刻度标签。 通过将此参数设置为False,可以将其关闭。linewidth=2指定网格线的宽度。color='gray'指定网格线的颜色。alpha=0.5指定网格线的透明度。linestyle='--'指定网格线的样式。
gl1.xlabels_top = False关闭上轴标签。 默认情况下,gridlines()函数为所有四个轴(左,下,上和右)绘制标签。 您可以通过更改此命令来打开或关闭其中的任何一个。gl1.ylabels_right = False关闭右轴标签。gl1.xlabel_style = {'size': 10, 'color': 'indigo', 'weight': 'bold'}定义要用于 x 轴标签的各种属性的字典。gl1.ylabel_style = {'size': 10, 'color': 'darkblue', 'weight': 'bold'}定义要用于 y 轴标签的各种属性的字典。ax1.set_title('PlateCarree - Default Ticks', color='green', size=15)打印具有各种属性的图表标题。ax1.text(0.5, -0.15, 'Longitude', va='bottom', ha='center', size=10, color='r', rotation='horizontal', rotation_mode='anchor', transform=ax1.transAxes)绘制 x 轴标签:(0.5, -0.15)是在坐标轴中从左至下的坐标,将在其中打印 x 轴标签。'Longitude'是要打印的 x 轴标签。va='bottom'指定标签应在底部垂直对齐。ha='center'指定标签应在中心水平对齐。size=10指定字体大小。color='r'指定字体颜色。rotation='horizontal'指定标签相对于轴的打印角度。 在这种情况下,角度设置为horizontal。rotation_mode='anchor'指定标签为锚对象。transform=ax1.transAxes指定给定的坐标在轴域坐标系中。
ax2 = fig.add_subplot(222, projection=ccrs.Mercator())定义第二张图表的轴域,该图表使用Mercator投影。gl2.xformatter = LONGITUDE_FORMATTER指定 x 刻度标签的格式选项。gl2.yformatter = LATITUDE_FORMATTER指定 y 刻度标签的格式选项。LONGITUDE_FORMATTER和LATITUDE_FORMATTER是gridliner函数内的预定义辅助函数。 它们都有自己的格式设置选项,但是在第二张图表中,我们都使用了所有默认参数。 他们基本上将东/西的方向设置为经度,将北/南的方向设置为纬度,并显示度数符号。 比较前两个图表的刻度标签以查看差异。gl3.xlines = False关闭第三张图表在 x 轴上着陆的网格线。 您也可以使用gl.ylines关闭 y 轴网格线。gl3.xlocator = mticker.FixedLocator([-180, -45, 0, 45, 180])定义 x 轴的刻度位置。 我们没有在gridliner的刻度位置中选择,而是在此处手动定义它们。ax4 = fig.add_subplot(2, 2, 4, projection=ccrs.PlateCarree(central_longitude=180))定义第四个图表的轴域,如下所示:(2, 2, 4)与(224)相同,并指定这是2 x 2图表网格中的第四张图表PlateCarree()是要使用的投影central_longitude=180指定纵轴的中心应为 180 度,而不是默认值 0
ax4.set_xticks([0, 60, 120, 180, 240, 300, 360], crs=ccrs.PlateCarree())定义 x 轴的刻度位置和标签。 在第四张图表中,我们没有使用gridlines()函数; 因此,我们必须手动设置刻度位置:crs=ccrs.PlateCarree()指定给定的刻度位置在PlateCarree坐标系中。 这与投影不同,投影指定了在绘制地图时要使用的坐标系。- 如果投影使用一个参考坐标系,并且刻度标签由另一坐标系提供,则通过指定提供数据的坐标系,它将在绘制地图之前将数据转换为投影坐标系。
ax4.set_yticks([-90, -60, -30, 0, 30, 60, 90], crs=ccrs.PlateCarree())定义 y 轴的刻度位置和标签。lon_formatter = LongitudeFormatter(zero_direction_label=True, number_format='.1f', degree_symbol='')定义纵轴的格式化器:zero_direction_label=True指定是否应使用E符号(向东)打印 0 度number_format='.1f'指定用于数字标签的小数点位数degree_symbol=''指定将不打印度数符号-默认选项是将其打印
[i.set_color("indigo") for i in ax4.get_xticklabels()]将'indigo'颜色应用于 x 轴上的刻度标签,[i.set_weight("bold") for i in ax4.get_xticklabels()]在其中打印刻度标签粗体:get_xticklabels()获取当前的刻度标签set_color()和set_weight()语句将指定的颜色和粗体字体应用于每个刻度标签- 接下来的两个语句对 y 轴刻度标签执行相同的操作,但是使用
darkblue颜色
执行上述代码后,您应该在屏幕上看到以下图:
应该注意的是,刻度标签和相关格式仅针对PlateCarree和Mercator投影定义。 对于其他投影,gridlines()会在没有刻度标签的情况下进行绘图,因此我们无法在gridlines()上使用draw_labels=True参数进行投影。
在地图上绘制位置
在本秘籍中,我们将学习如何在地图上绘制具有给定经度和纬度参数的位置。 这样就可以根据位置之间的相对位置直观地表示位置。 我们还将学习如何在地球上沿直线和球形方向连接两个位置。
准备
您需要使用以下命令导入所需的库:
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
操作步骤
这是绘制地图和全球各地的必要步骤。 您可以获取互联网上各个位置的经度和纬度信息。 在这里,我们将绘制主要城市,主要是国家的首都:
- 定义要在其上绘制地图的图形和轴域:
fig = plt.figure(figsize=(10, 5))
ax = fig.add_subplot(1, 1, 1, projection=ccrs.Robinson())
- 设置背景图像并添加海岸线特征:
ax.set_global()
ax.stock_img()
ax.coastlines()
- 使用给定的经度和纬度坐标绘制位置,如下所示:
ax.plot(-0.08, 51.53, 'o', transform=ccrs.PlateCarree(), markersize=7, color='r')
- 使用文本函数标记位置:
plt.text(-0.08, 51.53, 'London', size=10, color='indigo',
horizontalalignment='right', transform=ccrs.Geodetic())
- 现在,对于我们要绘制的所有城市,重复执行步骤 1 至步骤 4 ,如以下代码块所示:
ax.plot(37.6173, 55.7558, 'o', transform=ccrs.PlateCarree(), markersize=7, color='r')
plt.text(37.6173, 55.7558, 'Moscow', size=10, color='indigo',
horizontalalignment='left', transform=ccrs.Geodetic())
ax.plot(77.1, 28.7, 'o', transform=ccrs.PlateCarree(), markersize=7, color='r')
plt.text(77.1, 28.7, 'New Delhi', size=10, color='indigo',
horizontalalignment='left', transform=ccrs.Geodetic())
ax.plot(-118.2437, 34.0522, 'o', transform=ccrs.PlateCarree(), markersize=7, color='r')
plt.text(-118.2437, 34.0522, 'Los Angeles', size=10, color='indigo',
horizontalalignment='right', transform=ccrs.Geodetic())
ax.plot(-74, 40.7128, 'o', transform=ccrs.PlateCarree(), markersize=7, color='r')
plt.text(-74, 40.7128, 'New York', size=10, color='indigo',
horizontalalignment='left', transform=ccrs.Geodetic())
ax.plot(149.13, -35.2809, 'o', transform=ccrs.PlateCarree(), markersize=7, color='r')
plt.text(149.13, -35.2809, 'Canberra', size=10, color='indigo',
horizontalalignment='left', transform=ccrs.Geodetic())
ax.plot(116.4074, 39.9042, 'o', transform=ccrs.PlateCarree(), markersize=7, color='r')
plt.text(116.4074, 39.9042, 'Beijing', size=10, color='indigo',
horizontalalignment='right', transform=ccrs.Geodetic())
ax.plot(18.4241, -33.9249, 'o', transform=ccrs.PlateCarree(), markersize=7, color='r')
plt.text(18.4241, -33.9249, 'Cape Town', size=10, color='indigo',
horizontalalignment='left', transform=ccrs.Geodetic())
ax.plot(55.2708, 25.2048, 'o', transform=ccrs.PlateCarree(), markersize=7, color='r')
plt.text(55.2708, 25.2048, 'Dubai', size=10, color='indigo',
horizontalalignment='right', transform=ccrs.Geodetic())
ax.plot(139.6917, 35.6895, 'o', transform=ccrs.PlateCarree(), markersize=7, color='r')
plt.text(139.6917, 35.6895, 'Tokyo', size=10, color='indigo',
horizontalalignment='left', transform=ccrs.Geodetic())
ax.plot(-79.3832, 43.6532, 'o', transform=ccrs.PlateCarree(), markersize=7, color='r')
plt.text(-79.3832, 43.6532, 'Toronto', size=10, color='indigo',
horizontalalignment='right', transform=ccrs.Geodetic())
ax.plot(7.3986, 9.0765, 'o', transform=ccrs.PlateCarree(), markersize=7, color='r')
plt.text(7.3986, 9.0765, 'Abuja', size=10, color='indigo', # Capital of Nigeria
horizontalalignment='right', transform=ccrs.Geodetic())
ax.plot(-47.9218, -15.8267, 'o', transform=ccrs.PlateCarree(), markersize=7, color='r')
plt.text(-47.9218, -15.8267, 'Brasilia', size=10, color='indigo', # Capital of Brazil
horizontalalignment='right', transform=ccrs.Geodetic())
ax.plot(-99.1332, 19.4326, 'o', transform=ccrs.PlateCarree(),
markersize=7, color='r')
plt.text(-99.1332, 19.4326, 'Mexico City', size=10, color='indigo', # Capital of Brazil
horizontalalignment='right', transform=ccrs.Geodetic())
- 现在,绘制伦敦和新德里之间的直线和球面线,如下所示:
ax.plot([-0.08, 77.1], [51.53, 28.7], color='g', transform=ccrs.PlateCarree())
ax.plot([-0.08, 77.1], [51.53, 28.7], color='m', transform=ccrs.Geodetic())
- 最后,使用以下命令在屏幕上显示该图:
plt.show()
工作原理
这是前面代码的解释:
ax = fig.add_subplot(1, 1, 1, projection=ccrs.Robinson())定义带有Robinson投影的轴域。ax.plot(-0.08, 51.53, 'o', transform=ccrs.PlateCarree(), markersize=7, color='r')将位置绘制为伦敦,如下所示:(-0.08, 51.53)是伦敦的经度和纬度坐标。'o'是要在地图上绘制位置的标记。transform=ccrs.PlateCarree()指定提供经度和纬度参数的坐标系。 这些坐标将在内部转换为Robinson坐标,因为我们正在绘制带有Robinson投影的地图。markersize=7指定要在地图上绘制的点的大小,即 7 个点(一个点是 1/72 英寸)。color='r'将定位点被涂成红色。
plt.text(-0.08, 51.53, 'London', size=10, color='indigo', horizontalalignment='right', transform=ccrs.Geodetic())打印该位置的标签,其中包含名称:(-0.08, 51.53)代表打印标签的经度和纬度坐标。'London'表示要在标签上打印的文本。size=10是要打印的标签的大小。color='indigo'是标签的颜色。horizontalalignment='right'指定位置点应与标签的右侧对齐。transform=ccrs.Geodetic()指定坐标为经度和纬度,以度为单位。 还有一个笛卡尔等效项,即ccrs.Geocentric,其中坐标为常规 x,y 和 z 轴格式,以常规方式测量距离指标。
ax.plot([-0.08, 77.1], [51.53, 28.7], color='g', transform=ccrs.PlateCarree())绘制了一条连接伦敦和新德里的折线图,并指定了它们各自的经度和纬度坐标:[-0.08, 77.1]是伦敦和新德里的经度坐标[51.53, 28.7]是伦敦和新德里的纬度坐标color='g'表示两个城市之间绘制的线条的颜色将变为绿色transform=ccrs.PlateCarree()指定要使用的坐标系,在这种情况下为笛卡尔坐标系,因此将绘制一条直线
- 由于我们正在使用
transform=ccrs.Geodetic(),因此ax.plot([-0.08, 77.1], [51.53, 28.7], color='m', transform=ccrs.Geodetic())沿实际地球仪以球形格式绘制了相同的折线图。 由于颜色参数的'm'值,线条的颜色为洋红色。
执行代码后,您应该在屏幕上看到以下图:
绘制具有政治边界的国家地图
到目前为止,我们已经制作了覆盖全球的地图,这在您绘制例如全球公司办公室,跨大洲受到流行病影响的地区或跨许多国家的地震的地图时非常有用。
但是,如果要查看特定于某个地区的现象,该现象可能是一个国家,州,省甚至一个国家内的城市,则需要为地图设置较小的范围。 在本秘籍中,我们将学习如何做。
准备
通常,地图数据以形状文件的形式组织和分布。 为了能够读取这些文件并在地图上绘制数据,我们需要ShapeReader包,通常由用于绘制地图的软件提供ShapeReader包,在这种情况下,该程序为 cartopy。 源映射数据是由商业和开放源代码的几个不同实体准备,组织和分发的。 Cartopy 主要支持两种此类来源:一种可从这个页面获得。 另一个可以在这个页面中找到。 您可以参考这些站点,以获取有关每个包的更多信息。
在本章中,我们仅专注于自然地球数据提供的数据。
为了演示,我们将绘制三个国家/地区的地图:美国,英国和印度。 您只需更改经度和纬度范围内的范围,即可绘制任何其他国家,省或城市的地图。
您需要使用以下命令导入所需的库:
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER
import cartopy.io.shapereader as shpreader
操作步骤
这是绘制地图所需的步骤 :
- 定义图:
fig = plt.figure(figsize=(16,8))
- 用
PlateCarree投影定义轴域:
ax1 = fig.add_subplot(131, projection=ccrs.PlateCarree())
- 如下定义美国的经度和纬度范围:
ax1.set_extent([-130, -66.5, 25, 47], ccrs.Geodetic())
- 使用
add_feature()函数绘制美国地图。 为了方便起见,Cartopy 为美国提供了此功能,因此我们不必读取外部形状文件:
ax1.add_feature(cfeature.STATES, facecolor='wheat')
- 定义
gridlines()函数如下:
gl1 = ax1.gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
linewidth=2, color='gray', alpha=0.5,
linestyle='--')
- 关闭上轴和右轴的标签,如下所示:
gl1.xlabels_top = False
gl1.ylabels_right = False
- 应用经度和纬度格式化程序以按适当的方向以度显示标签,如下所示:
gl1.xformatter = LONGITUDE_FORMATTER
gl1.yformatter = LATITUDE_FORMATTER
- 定义要在 x 和 y 标签上应用的属性的字典:
gl1.xlabel_style = {'size': 10, 'color': 'b'}
gl1.ylabel_style = {'size': 10, 'color': 'r', 'weight': 'bold'}
- 如下打印标题和 x 和 y 标签:
ax1.set_title('United States of America(lon/lat)\n[-130, -66.5, 25,
47]', color='g', size=15)
ax1.text(0.5, -0.2, 'Longitude', va='bottom', ha='center', size=10,
color='r', rotation='horizontal', rotation_mode='anchor',
weight='bold', transform=ax1.transAxes)
ax1.text(-0.1, 0.55, 'Latitude', va='bottom', ha='center', size=10,
color='b', rotation='vertical', rotation_mode='anchor',
weight='bold', transform=ax1.transAxes)
- 使用墨卡托投影定义轴域,以绘制印度地图:
ax2 = fig.add_subplot(132, projection=ccrs.Mercator())
- 设置印度的经度和纬度范围如下:
ax2.set_extent([68.12, 97.42, 8.07, 37.1], ccrs.Geodetic())
- 从自然地球数据中读取包含国家/地区特定数据的形状文件:
shapename = 'admin_1_states_provinces_lakes_shp'
states_shp = shpreader.natural_earth(resolution='10m',
category='cultural', name=shapename)
- 在地图上绘制国家的不同部分,如下所示:
for state in shpreader.Reader(states_shp).geometries():
ax2.add_geometries([state], ccrs.PlateCarree(),
facecolor='wheat', edgecolor='black')
- 定义网格线和轴标签,并以适当的格式将它们与标题一起打印,如在美国所做的那样,并在此处显示:
gl2 = ax2.gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
linewidth=2, color='gray', alpha=0.5,
linestyle='--')
gl2.xlabels_top = False
gl2.ylabels_right = False
gl2.xformatter = LONGITUDE_FORMATTER
gl2.yformatter = LATITUDE_FORMATTER
gl2.xlabel_style = {'size': 10, 'color': 'blue'}
gl2.ylabel_style = {'size': 10, 'color': 'red', 'weight': 'bold'}
ax2.set_title('India(lon/lat)\n[68.12, 97.42, 8.07, 37.1]',
color='g', size=15)
- 现在,对英国重复上述步骤:
ax3 = fig.add_subplot(133, projection=ccrs.Mercator())
ax3.set_extent([-8.62, 1.77, 49.9, 60.84], ccrs.Geodetic())
for state in shpreader.Reader(states_shp).geometries():
ax3.add_geometries([state], ccrs.PlateCarree(),
facecolor='wheat', edgecolor='black')
gl3 = ax3.gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
linewidth=2,
color='gray', alpha=0.5, linestyle='--')
gl3.xlabels_top = False
gl3.ylabels_right = False
gl3.xformatter = LONGITUDE_FORMATTER
gl3.yformatter = LATITUDE_FORMATTER
gl3.xlabel_style = {'size': 10, 'color': 'blue'}
gl3.ylabel_style = {'size': 10, 'color': 'red', 'weight': 'bold'}
ax3.set_title('United Kingdom(lon/lat)\n[-8.62, 1.77, 49.9, 60.84]',
color='g', size=15)
16.最后,使用以下命令在屏幕上显示该图:
plt.tight_layout(w_pad=5)
plt.show()
工作原理
这是代码的说明:
-
ax1.set_extent([-130, -66.5, 25, 47], ccrs.Geodetic())指定要绘制的区域范围,如下所示:(-130, -66.5)是美国的最小和最大经度坐标(25, 47)是美国的最小和最大纬度坐标ccrs.Geodetic()指定所使用的数据坐标格式为经度和纬度,以度为单位
-
ax1.add_feature(cfeature.STATES, facecolor='wheat')绘制了美国各州的内部边界。 Cartopy 将此作为一种特征,类似于我们先前了解的其他物理特征,例如陆地,海洋,河流和湖泊。 对于其他国家/地区,我们将不得不从形状文件中获取数据并将其单独绘制。 -
gridlines()及其相关的标签格式与前面的秘籍相同。 -
ax1.set_title('United States of America(lon/lat)\n[-130, -66.5, 25, 47]', color='g', size=15)打印图表的标题,包括第一行的名称,以及下一行的经度和纬度坐标(\n,换行符,将文本分为两行)。 -
ax2.set_extent([68.12, 97.42, 8.07, 37.1], ccrs.Geodetic())指定要在第二个轴域上绘制的区域的范围,如下所示:(68.12, 97.42)是印度的最小和最大经度坐标。(8.07, 37.1)是印度的最小和最大纬度坐标。crs.Geodetic()指定数据坐标为经度和纬度,以度为单位。
-
shapename = 'admin_1_states_provinces_lakes_shp'指定要从自然地球数据站点下载以绘制地图的形状文件的名称。 它不是确切的文件名,而是可用的各种类型中的文件类型。 类型很多,例如admin 0,admin 1,populated places,railroads,roads,airports和ports。 有关详细信息,请参考自然地球数据站点,该站点可在这个页面上找到。 -
states_shp = shpreader.natural_earth(resolution='10m', category='cultural', name=shapename)从自然地球下载数据,解压缩和读取形状文件:resolution='10m'指定数据中的详细程度。 一共有三个级别,10m,50m和110m,其中10m最详细,110m提供了更汇总的数据级别。category='cultural'指定数据的类别。 同样,存在三类,cultural,physical和raster。Cultural涉及政治和行政边界,physical涉及陆地,海洋,河流和湖泊,raster涉及环境和气候相关条件的数据。name=shapename指定要以形状文件格式下载的数据类型。
-
for state in shpreader.Reader(states_shp).geometries():启动for循环以读取在上一步中下载的形状文件的内容:shapereader访问文件,解压缩并下载形状文件的内容Reader访问形状文件的内容Reader下有两种方法,即records和geometries:geometries访问要绘制的形状,并且在我们知道形状文件的元数据时很有用。 在这种情况下,我们知道我们正在绘制国家内部的州边界,因此我们直接使用geometries。- 当我们需要有关形状文件内容的元数据的其他信息时,将使用
records方法。 一旦有了元数据,就可以使用records.geometries访问要绘制的形状。
-
在
for循环的每次迭代中,给定state边界的ax2.add_geometries([state], ccrs.PlateCarree(), facecolor='wheat', edgecolor='black')图。 它使用black颜色作为边界边缘,使用wheat颜色作为状态区域。 -
正如我们在前面的秘籍中所了解的,其余的代码处理网格线和相关的格式。
-
我们重复绘制英国的完全相同的过程。 我们只需要设置要绘制的区域的适当范围,如下所示:
ax3.set_extent([-8.62, 1.77, 49.9, 60.84], ccrs.Geodetic())设置英国的范围(-8.62, 1.77)是英国的最小和最大经度坐标(49.9, 60.84)是英国的最小和最大纬度坐标
执行上述代码后,您应该在屏幕上看到以下地图:
使用 GeoPandas 和 Cartopy 绘制国家地图
在前面的秘籍中,我们使用shapereader下载文件,并使用Reader读取形状文件的内容并绘制它们。shapereader和Reader都是由 Cartopy 提供的。 在本秘籍中,我们将继续使用shapereader下载所需的形状文件,但使用 GeoPandas 读取并绘制形状文件的内容。 我们在第 6 章和“带有高级功能的绘图”中更早地使用了 GeoPandas 来绘制本书那部分中的地图。
我们将绘制与前面秘籍相同的三个国家地图。 但是,我们将使用两种不同类型的文件,admin 0和admin 1,并为每种类型绘制三个国家/地区,总共有六个图表。
准备
您需要使用以下命令导入所需的库:
import matplotlib.pyplot as plt
import numpy as np
import geopandas
from cartopy.io import shapereader
import cartopy.crs as ccrs
操作步骤
以下是绘制国家地图的步骤:
- 如下定义图:
fig = plt.figure(figsize=(12, 6))
- 定义六个轴域以绘制六个不同的图形,所有图形均带有
PlateCarree投影。 这次,我们不绘制背景图像,并且也没有添加coastlines():
ax1 = fig.add_subplot(231, projection=ccrs.PlateCarree())
ax2 = fig.add_subplot(232, projection=ccrs.PlateCarree())
ax3 = fig.add_subplot(233, projection=ccrs.PlateCarree())
ax4 = fig.add_subplot(234, projection=ccrs.PlateCarree())
ax5 = fig.add_subplot(235, projection=ccrs.PlateCarree())
ax6 = fig.add_subplot(236, projection=ccrs.PlateCarree())
- 使用
shapereader下载admin_0形状文件:
shpfilename = shapereader.natural_earth(resolution='10m',
category='cultural', name='admin_0_countries')
- 将形状文件的内容读取到 Pandas 数据帧中:
df0 = geopandas.read_file(shpfilename)
- 在地图投影上设置美国的范围:
ax1.set_extent([-130, -66.5, 25, 50], crs=ccrs.PlateCarree())
- 提取与美国有关的多边形(即构成国家的块):
poly = df0.loc[df0['ADMIN'] == 'United States of America']['geometry']
- 使用
geometries方法在地图上绘制多边形,如下所示:
ax1.add_geometries(poly, crs=ccrs.PlateCarree(), facecolor='none', edgecolor='0.5')
- 打印图的标题:
ax1.set_title('United States of America - Admin0')
- 对印度,然后对英国重复步骤 4 至步骤 8 。 请参见以下示例:
ax2.set_extent([-8.62, 1.77, 49.9, 60.84], crs=ccrs.PlateCarree()) # United Kingdom
poly = df0.loc[df0['ADMIN'] == 'United Kingdom']['geometry']
ax2.add_geometries(poly, crs=ccrs.PlateCarree(), facecolor='none',
edgecolor='0.5')
ax2.set_title('United Kingdom - Admin0')
ax3.set_extent([68.12, 97.42, 8.07, 37.1], crs=ccrs.PlateCarree()) # India
poly = df0.loc[df0['ADMIN'] == 'India']['geometry']
ax3.add_geometries(poly, crs=ccrs.PlateCarree(), facecolor='none', edgecolor='0.5')
ax3.set_title('India - Admin0')
- 使用
shapereader下载admin_1形状文件:
shpfilename = shapereader.natural_earth(resolution='10m',
category='cultural',
name='admin_1_states_provinces_lakes_shp')
df1 = geopandas.read_file(shpfilename)
- 对每个国家/地区重复步骤 4 至步骤 8 ,如下所示:
ax4.set_extent([-130, -66.5, 25, 50], crs=ccrs.PlateCarree()) # United States of America
poly = df1.loc[df1['admin'] == 'United States of America']
['geometry']
ax4.add_geometries(poly, crs=ccrs.PlateCarree(), facecolor='none',
edgecolor='0.5')
ax4.set_title('United States of America - Admin1')
ax5.set_extent([-8.62, 1.77, 49.9, 60.84], crs=ccrs.PlateCarree()) # United Kingdom
poly = df1.loc[df1['admin'] == 'United Kingdom']['geometry']
ax5.add_geometries(poly, crs=ccrs.PlateCarree(), facecolor='none',
edgecolor='0.5')
ax5.set_title('United Kingdom - Admin1')
ax6.set_extent([68.12, 97.42, 8.07, 37.1], crs=ccrs.PlateCarree()) # India
poly = df1.loc[df1['admin'] == 'India']['geometry']
ax6.add_geometries(poly, crs=ccrs.PlateCarree(), facecolor='none',
edgecolor='0.5')
ax6.set_title('India - Admin1')
- 最后,在屏幕上显示图,如下所示:
plt.show()
工作原理
这是前面代码的解释:
shpfilename = shapereader.natural_earth(resolution='10m', category='cultural', name='admin_0_countries')从自然地球数据网站下载所需的形状文件。df0 = geopandas.read_file(shpfilename)将形状文件的内容读取到df0, Pandas 数据帧对象中。ax1.set_extent([-130, -66.5, 25, 50], crs=ccrs.PlateCarree())设置美国范围。poly = df0.loc[df0['ADMIN'] == 'United States of America']['geometry']从 Pandas 数据帧读取要绘制为多边形的特定块:df0数据帧有一个'ADMIN'列,用于存储国家名称,用于提取与美国有关的特定内容。geometry是df0中的另一列,用于存储形成特定国家/地区的区块的信息。- 此形状文件中每个国家/地区只有一个对象。 因此,它仅将国家的轮廓绘制为一个多边形,而没有州或省的内部块。
ax1.add_geometries(poly, crs=ccrs.PlateCarree(), facecolor='none', edgecolor='0.5')使用geometries方法在地图上绘制多边形:facecolor='none'指定不使用任何颜色填充块。edgecolor = '0.5'指定使用灰色绘制边缘。
ax1.set_title('United States of America - Admin0')打印图的标题。shpfilename = shapereader.natural_earth(resolution='10m', category='cultural', name='admin_1_states_provinces_lakes_shp')读取我们在先前秘籍中使用的admin_1形状文件。 这不仅将具有admin0中的国家边界,而且还将具有内部州和省边界。df1 = geopandas.read_file(shpfilename)将形状文件内容读取到 Pandas 数据帧中。poly = df1.loc[df1['admin'] == 'United States of America']['geometry']过滤形成美国的多边形。 在这种情况下,geometry列将为每个国家/地区提供多个对象,并指定该国家/地区内的州和省。- 其余步骤与
admin 0文件的步骤完全相同。
执行上述代码后,您应该在屏幕上看到以下地图。 应当注意,我们没有使用默认图像作为背景,因此,我们在这里看不到彩色图像。 第一行只是国家/地区的轮廓,而第二行中的图则描绘了每个国家/地区内的州和省,如Admin 0和Admin 1文件中所示:
绘制世界人口稠密的地方
在此秘籍中,我们将绘制全球人类居住的位置。 我们将使用自然地球数据网站上的相应形状文件。
准备
您需要使用以下命令导入所需的库:
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.io.shapereader as shpreader
操作步骤
以下是绘制地图所涉及的步骤:
- 使用
PlateCarree投影定义图形和轴域:
plt.figure(figsize=(12, 6))
ax = plt.axes(projection=ccrs.PlateCarree())
- 如下设置背景图像和海岸线:
ax.stock_img()
ax.coastlines()
- 从自然地球数据网站下载所需的形状文件:
shp_fn = shpreader.natural_earth(resolution='10m',
category='cultural', name='populated_places')
- 获取每个位置的特定坐标,如下所示:
xy = [pt.coords[0] for pt in shpreader.Reader(shp_fn).geometries()]
- 使用以下命令解压缩坐标:
x, y = zip(*xy)
- 使用散点图绘制这些点:
ax.scatter(x,y, transform=ccrs.Geodetic())
- 绘制图的标题,如下所示:
ax.set_title('Populated places of the world.')
- 最后,使用以下命令在屏幕上显示地图:
plt.show()
工作原理
这是前面代码的解释:
shp_fl = shpreader.natural_earth(resolution='10m', category='cultural', name='populated_places')下载形状文件,其中包含人类填充的位置信息xy = [pt.coords[0] for pt in shpreader.Reader(shp_fl).geometries()]将位置的坐标提取到xy变量中x, y = zip(*xy)将坐标解压缩为 x 和 y 坐标ax.scatter(x,y, transform=ccrs.Geodetic())绘制位置的散点图ax.set_title('Populated places of the world.')设置绘图的标题
执行上述代码后,您应该在屏幕上看到以下地图。 蓝点代表存在人类的位置:
绘制人口前五名和后五名的国家
在本秘籍中,我们将学习如何提取每个国家的人口数据,按人口数量对它们进行排序,并在人口图上绘制按人口计算的前五名和后五名国家。 我们将下载并使用110m分辨率的admin 0形状文件。
准备
您需要使用以下命令导入所需的库:
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.io.shapereader as shpreader
操作步骤
以下是绘制地图所需的步骤:
- 使用以下命令下载所需的形状文件:
shpfilename = shpreader.natural_earth(resolution='110m', category='cultural', name='admin_0_countries')
- 提取数据并对其进行排序,以按人口升序获得国家/地区,如下所示:
reader = shpreader.Reader(shpfilename)
countries = reader.records()
country = next(countries)
population = lambda country: country.attributes['POP_EST']
sort_by_pop = sorted(countries, key=population)
- 提取前五个和最后五个条目,分别代表人口不足的前五名和前五名的国家。 从网上离线获取相应的经度和纬度坐标:
## get the first 5 entries that represent lowest population
B5_countries_by_pop = sort_by_pop[:5]
B5_Country_Names = ', '.join([country.attributes['NAME_LONG'] for
country in B5_countries_by_pop])
## get the last 5 entries that represent highest population
T5_countries_by_pop = sort_by_pop[-5:]
T5_Country_Names = ', '.join([country.attributes['NAME_LONG'] for
country in T5_countries_by_pop])
##B5_Country_Names = ['French Southern and Antarctic Lands',
'Falkland Islands', 'Antarctica', 'Greenland', #'Northern Cyprus']
B5_lat = [49.28, 51.796, 82.862, 71.71, 35.32]
B5_lon = [69.35, 59.523, 135, 42.60, 33.31]
##T5_Country_Names = ['Brazil', 'Indonesia', 'United States',
'India', 'China']
T5_lat = [-14.2350, -0.7893, 37.0902, 20.5937, 40]
T5_lon = [-51.9253, 113.9213, -95.7129, 78.9629, 116.5]
- 定义图形,轴域并设置默认值:
fig = plt.figure(figsize=(10, 5))
ax = fig.add_subplot(1, 1, 1, projection=ccrs.Robinson())
ax.set_global()
ax.stock_img()
ax.coastlines()
- 将这些点绘制在全球地图上,如下所示:
ax.plot(B5_lon, B5_lat, 'o', transform=ccrs.PlateCarree(), markersize=10, color='r')
ax.plot(T5_lon, T5_lat, 'o', transform=ccrs.PlateCarree(), markersize=10, color='g')
- 使用
text扩展嵌入函数来绘制与每个点相对应的标签:
plt.text(B5_lon[0], B5_lat[0], 'FSAL', size=12, color='indigo',
horizontalalignment='left', transform=ccrs.Geodetic())
plt.text(B5_lon[1], B5_lat[1], 'FI', size=12, color='indigo',
horizontalalignment='left', transform=ccrs.Geodetic())
plt.text(B5_lon[2], B5_lat[2], 'Antarctica', size=12,
color='indigo', horizontalalignment='left', transform=ccrs.Geodetic())
plt.text(B5_lon[3], B5_lat[3], 'Greenland', size=12, color='indigo',
horizontalalignment='right', transform=ccrs.Geodetic())
plt.text(B5_lon[4], B5_lat[4], 'NC', size=12, color='indigo',
horizontalalignment='left', transform=ccrs.Geodetic())
plt.text(T5_lon[0], T5_lat[0], 'Brazil', size=12, color='m',
horizontalalignment='left', transform=ccrs.Geodetic())
plt.text(T5_lon[1], T5_lat[1], 'Indonesia', size=12, color='m',
horizontalalignment='left', transform=ccrs.Geodetic())
plt.text(T5_lon[2], T5_lat[2], 'United States', size=12, color='m',
horizontalalignment='left', transform=ccrs.Geodetic())
plt.text(T5_lon[3], T5_lat[3], 'India', size=12, color='m',
horizontalalignment='left', transform=ccrs.Geodetic())
plt.text(T5_lon[4], T5_lat[4], 'China', size=12, color='m',
horizontalalignment='right', transform=ccrs.Geodetic())
- 使用以下命令在屏幕上显示图:
plt.show()
工作原理
这是代码的说明:
shpfilename = shpreader.natural_earth(resolution='110m', category='cultural', name='admin_0_countries')从自然地球数据网站下载所需的形状文件。reader = shpreader.Reader(shpfilename)设置读取器以从形状文件提取数据。countries = reader.records()设置生成器对象以开始读取文件。country = next(countries)提取下一个国家/地区记录。population = lambda country: country.attributes['POP_EST']定义了一个匿名函数,该函数返回给定国家记录的人口。'POP_EST'是导入的国家/地区记录的属性之一。lambda是用于定义临时的一次性使用匿名函数的 Python 构造。sort_by_pop = sorted(countries, key=population)按填充顺序对导入的形状文件进行排序,映射到countries。B5_countries_by_pop = sort_by_pop[:5]从排序的文件中提取前五个记录。 这些记录代表了人口规模排名前五的国家。B5_Country_Names = ', '.join([country.attributes['NAME_LONG'] for country in B5_countries_by_pop])选取国家/地区的长名称,如这五个国家/地区的NAME_LONG属性中所给。T5_countries_by_pop = sort_by_pop[-5:]从排序的文件中拾取最后五个条目。 这些条目代表了人口规模排名前五的国家。T5_Country_Names = ', '.join([country.attributes['NAME_LONG'] for country in T5_countries_by_pop])为每个国家/地区选择了长名。B5_lat = [49.28, 51.796, 82.862, 71.71, 35.32]和B5_lon = [69.35, 59.523, 135, 42.60, 33.31]是排名靠后的五个国家/地区的经度和纬度坐标列表。T5_lat = [-14.2350, -0.7893, 37.0902, 20.5937, 40]和T5_lon = [-51.9253, 113.9213, -95.7129, 78.9629, 116.5]是前五个国家/地区的经度和纬度坐标。fig = plt.figure(figsize=(10, 5))定义大小为(10, 5)英寸的图形。ax = fig.add_subplot(1, 1, 1, projection=ccrs.Robinson())定义使用Robinson投影绘制地图的轴域。ax.plot(B5_lon, B5_lat, 'o', transform=ccrs.PlateCarree(), markersize=10, color='r')使用'0'标记绘制底部的五个国家/地区,标记设置为 10 点,颜色为红色。ax.plot(T5_lon, T5_lat, 'o', transform=ccrs.PlateCarree(), markersize=10, color='g')使用'0'标记绘制前五个国家/地区的位置,将其设置为大小为 10 点,并用绿色标记。plt.text()语句为这 10 个位置中的每个位置打印标签,并带有各自的长名称。 对于某些国家/地区,我们使用了缩写,因为它们的名称对于地图来说太长了。 您可以在本章的代码文件中看到它们的全名。
执行上述代码后,您应该在屏幕上看到以下图:
绘制全球温度
在本秘籍中,我们将学习如何绘制全球给定温度的图表,以可视化它们相对彼此的外观。 您需要从这里下载用于绘制地图所需的温度文件。
准备
您需要使用以下命令导入所需的库:
from netCDF4 import Dataset
import matplotlib.pylab as plt
import numpy as np
from matplotlib import cm
import cartopy.crs as ccrs
from cartopy.util import add_cyclic_point
操作步骤
以下是绘制地图所需的步骤:
- 如下加载用于绘制地图的温度文件:
netCDF_temp = Dataset('temperature_annual_1deg.nc')
- 对于要在地图上绘制的所有点,提取经度和纬度坐标以及相应的摄氏温度:
lat = netCDF_temp.variables['lat'][:]
lon = netCDF_temp.variables['lon'][:]
temp = netCDF_temp.variables['t_an'][0,0,:,:]
- 在温度和经度上添加循环点以删除白色垂直线,否则该垂直线将显示在图形上:
temp_cyc, lon_cyc = add_cyclic_point(temp, coord=lon)
- 使用
Robinson投影定义图形和轴域:
plt.figure(figsize=(12,6))
ax = plt.subplot(111, projection=ccrs.Robinson())
- 使用以下命令将背景图像和海岸线添加到地图中:
ax.stock_img()
ax.coastlines()
- 使用
seismic颜色表使用pcolormesh函数绘制温度:
temp_map = ax.pcolormesh(lon_cyc, lat, temp_cyc, vmin=-10, vmax=40,
transform=ccrs.PlateCarree(),cmap=cm.seismic)
- 绘制带有
'horizontal'方向的颜色条,如下所示:
plt.colorbar(temp_map, orientation='horizontal')
- 使用以下命令在屏幕上显示图:
plt.show()
工作原理
这是前面代码的解释:
netCDF_temp = Dataset('temperature_annual_1deg.nc')加载温度数据。 这是一个netCDF-compliant文件,因此将需要适当的工具来读取数据,我们已经在此秘籍的“准备”部分中导入了该数据集。lon = netCDF_temp.variables['lon'][:]和lat = netCDF_temp.variables['lat'][:]提取要绘制温度的位置的经度和纬度坐标。temp = netCDF_temp.variables['t_an'][0,0,:,:]提取第一层的温度。temp_cyc, lon_cyc = add_cyclic_point(temp, coord=lon)添加循环点以避免经度为零的垂直白线。temp_map = ax.pcolormesh(lon_cyc, lat, temp_cyc, vmin=-10, vmax=40, transform=ccrs.PlateCarree(),cmap=cm.seismic)绘制所需的温度图,如下所示:lon_cyc,lat和temp_cyc是要绘制的经度,纬度和温度数据vmin和vmax指定要在地图上绘制的最低和最高温度cmap=cm.seismic指定将使用seismic颜色表
plt.colorbar(temp_map, orientation='horizontal')以水平方向绘制颜色条。
执行代码后,您应该在屏幕上看到以下地图:
绘制时区
在本秘籍中,我们将学习如何在地图上绘制时区。自然地球数据网站上提供了时区形状文件,因此我们可以像过去一样使用shapereader下载它。 但是,我们已离线下载文件,并在此处使用它来演示 Cartopy 提供的另一个函数:ShapelyFeature。
准备
您需要使用以下命令导入所需的库:
import matplotlib.pyplot as plt
import numpy as np
import cartopy.crs as ccrs
from cartopy.io.shapereader import Reader
from cartopy.feature import ShapelyFeature
import matplotlib.ticker as mticker
操作步骤
以下是在地图上绘制时区所需的步骤:
- 使用
PlateCarree投影定义图形和轴域:
plt.figure(figsize=(12, 6))
ax = plt.axes(projection=ccrs.PlateCarree())
- 如下将背景图像和海岸线特征应用于地图:
ax.stock_img()
ax.coastlines(zorder=0)
- 使用
ShapelyFeature函数读取时区形状文件的内容作为特征:
shape_feature = ShapelyFeature(Reader('ne_10m_time_zones.shp').geometries(),
ccrs.PlateCarree(), edgecolor='black')
- 在地图上绘制特征,如下所示:
ax.add_feature(shape_feature, alpha=0.4, zorder=5, lw=1)
- 应用
gridlines()函数,如下所示:
gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
linewidth=2, color='gray', alpha=0.5, linestyle='--')
- 关闭左,上和右轴标签:
gl.xlabels_top = False
gl.ylabels_left = False
gl.ylabels_right = False
- 为 x 轴应用固定的刻度位置,覆盖默认刻度,如下所示:
gl.xlocator = mticker.FixedLocator(np.linspace(-180, 180, 25))
- 将 x 轴上的刻度标签的格式设置如下:
gl.xlabel_style = {'size': 10, 'color': 'blue'}
- 绘制地图标题:
ax.set_title('Global Time Zones', size=15, color='g')
- 最后,使用以下命令在屏幕上显示地图:
plt.show()
工作原理
这是前面代码的解释:
ax.coastlines(zorder=0)如下在地图上绘制海岸线:zorder=0指定应首先绘制海岸线,以免它们进入前景并遮盖时区线
shape_feature = ShapelyFeature(Reader('ne_10m_time_zones.shp').geometries(),ccrs.PlateCarree(), edgecolor='black')创建一个可以添加到地图的特征对象:- 到目前为止,
Reader从形状文件中提取内容 ShapelyFeature将内容准备为可使用add_feature方法添加到地图的特征
- 到目前为止,
ax.add_feature(shape_feature, alpha=0.4, zorder=5, lw=1)将在上一步中创建的地图项添加到地图中:shape_feature是要绘制的特征alpha=0.4指定透明度级别zorder=5指定时区线的打印时间比海岸线晚,因此它们出现在前景中,海岸线显示在背景中lw=1指定时区线的宽度
- 地图上有 24 条时区线:经度 0 度的左侧 12 条,右侧 12 条。 经度零度本身表示格林威治标准时间(GMT),因此零度右侧的纵向坐标位于 GMT 之前,零度左侧的经向坐标在格林威治标准时间后面。
gridlines()和相关的格式与本章到目前为止的操作相似。gl.xlocator = mticker.FixedLocator(np.linspace(-180, 180, 25))在 x 轴上施加刻度,从 -180 度到 +180 度以 25 个相等的间隔(每 15 个间隔)开始。- 每 15 度经度代表时区 1 小时的时间。 因此,经度为零度右侧的第一个时区比格林尼治标准时间(经度 7.5 度)早 30 分钟。 同样,零度经度左侧的第一个时区比格林尼治标准时间晚 30 分钟。 印度比格林尼治标准时间早 5.5 小时。 这些时区表示不使用夏令时的标准时间。
执行上述代码后,您应该在屏幕上看到以下图:
绘制动画地图
在本秘籍中,我们将学习如何为三维可视化绘制动画地图。
准备
您需要使用以下命令导入所需的库:
import cartopy.crs as ccrs
import matplotlib.animation as animation
import matplotlib.pyplot as plt
import numpy as np
操作步骤
以下是绘制动画地图并将其保存为 MP4 文件的步骤:
- 设置要在其上制作地图动画的后端,如下所示:
import matplotlib
matplotlib.use('tkagg')
- 定义图:
fig = plt.figure(figsize=(6, 6))
- 定义一个函数,以使用新的帧不断更新地图:
def animate(longitude):
ax = plt.gca()
ax.remove()
ax = plt.axes([0, 0, 1, 1], projection=ccrs.Geostationary(central_longitude=longitude))
ax.set_global()
ax.coastlines()
ax.stock_img()
ax.gridlines()
- 激活动画,如下所示:
ani = animation.FuncAnimation(fig, animate, frames=np.linspace(0, 360, 10),
interval=50, repeat=True, repeat_delay=500)
- 使用以下命令将动画地图另存为 MP4 文件:
ani.save("Geostationary.mp4")
- 使用以下命令在屏幕上显示动画:
plt.show()
工作原理
这是前面代码的解释:
matplotlib.use('tkagg')设置 Tkinter 后端以显示动画fig = plt.figure(figsize=(6, 6))定义图形def animate(longitude):是用于使用新框架更新地图的函数:ax = plt.gca()获取当前活动轴域的引用。ax.remove()删除该轴域上的绘图(如果已经存在)。ax = plt.axes([0, 0, 1, 1], projection=ccrs.Geostationary(central_longitude=longitude))使用Geostationary投影刷新此函数接收到的当前经度轴域上的地图。ax.coastlines()将海岸线特征添加到地图。ax.stock_img()将背景图像添加到地图。ax.gridlines()将网格线添加到图像。 我们此处无法使用draw_labels=True参数,因为我们正在使用Geostationary投影。
ani = animation.FuncAnimation(fig, animate, frames=np.linspace(0, 360, 10), interval=50, repeat=True, repeat_delay=500)激活动画:fig是要在其上绘制地图的图形对象。animate是先前定义的动画的更新函数。frames是 10 个条目的列表,其中条目平均间隔 36 度。 此数字将自动传递到动画函数,该函数会接收该数字并映射到当前经度。 因此,地球在每次迭代中旋转 36 度。interval=50指定连续帧之间的时间间隔(以毫秒为单位)。repeat=True指定在显示所有帧之后,应重复该循环,以便动画永远持续下去。repeat_delay=500指定开始下一个周期之前的时间延迟(以毫秒为单位)。
ani.save("Geostationary.mp4")将动画和文件名Geostationary.mp4保存到当前工作目录中
运行前面的代码后,您应该在屏幕上看到类似以下的内容(这里是动画图的快照)。 您可以在代码目录中找到 MP4 文件,以查看实际的动画:
十四、使用 Seaborn 工具包的探索性数据分析
在本章中,我们将学习如何使用另一种第三方工具箱seaborn和绘制以下类型图形的秘籍:
-
关系图(
sns.relplot):- 线形图(
sns.lineplot) - 散点图(
sns.scatterplot)
- 线形图(
-
类别图(
sns.catplot):- 条带图和群图(
sns.stripplot,sns.swarmplot) - 盒子图和 Boxn 图(
sns.boxplot,sns.boxnplot) - 条形图和计数图(
sns.barplot,sns.countplot) - 提琴图(
sns.violinplot) - 点图(
sns.pointplot)
- 条带图和群图(
-
分布图:
- 分布,核密度估计(KDE)和地毯图(
sns.distplot,sns.kdeplot和sns.rugplot)
- 分布,核密度估计(KDE)和地毯图(
-
回归图:
- 回归图和残差图(
sns.regplot,sns.residplot) - LM 图(
sns.lmplot)
- 回归图和残差图(
-
多图网格:
- 联合图和联合网格图(
sns.jointplot,sns.JointGrid) - 配对图和配对网格图(
sns.pairplot,sns.PairGrid) - 方面网格(
sns.FacetGrid)
- 联合图和联合网格图(
-
矩阵图:
- 热图(
sns.heatmap) - 群集图(
sns.clustermap)
- 热图(
介绍
Seaborn 是基于 Matplotlib 构建的功能强大的可视化工具。 它使多变量探索性数据分析更加容易和直观,并且增加了一些新类型的图,并且其背景样式和颜色表更加令人愉悦。 它具有许多内置的统计函数,使其成为统计数据分析的首选工具。 它还具有非常详尽的在线文档,您可以在这个页面中找到它们。
我们将使用两个数据集来演示大多数海洋特征。 您已经熟悉了一个数据集Wine Quality,我们将引入一个新数据集,其中包含来自虚拟小吃店的零食销售数据。 无需在每个秘籍中多次阅读这些文件,我们将在本节中对它们进行描述,随后我们将仅使用它们来绘制图形。 这与我们到目前为止在本书中采用的方法略有不同。 这两个数据文件都可以在本章的代码库中找到。
零食销售数据集
该数据集(在代码库中提供)包含有关给定日期,星期几,是否为周末以及当天是否促销的各种商品的销售信息。 我们拥有三年的数据:2015 年,2016 年和 2017 年。数据集的前五行如下所示:
然后,我们将添加两个有助于绘制所需图形的派生变量:Month(1 至 12)和Quarter(1 至 4)。 添加这些变量后,的前五行如下所示:
以下代码块读取 Excel 文件并添加其他变量:
import pandas as pd
import numpy as np
snacks_sales = pd.read_csv('Snacks_Data.csv')
snacks_sales['Month'] = pd.DatetimeIndex(snacks_sales['Date']).month
Quarter_Mapping = {1:1, 2:1, 3:1, 4:2, 5:2, 6:2, 7:3, 8:3, 9:3, 10:4,
11:4, 12:4}
snacks_sales['Quarter'] = snacks_sales['Month'].map(Quarter_Mapping)
葡萄酒品质
该数据集具有 11 个影响葡萄酒质量的属性。Quality的等级从 3 到 8,然后我们将 3 和 4 映射到Low,将 5 和 6 映射到Med,将 7 和 8 映射到High以创建一个新变量:Quality。
数据集的前五行如下所示:
我们还将为Wine Quality数据集计算相关矩阵,我们将在一些图中使用它们。
以下是用于读取其他变量并将其添加到Wine Quality数据集的代码块:
import pandas as pd
## Read the data from a csv file into pandas data frame
wine_quality = pd.read_csv('winequality.csv', delimiter=';')
## Map numeric Quality codes to "Low", "Med" and "High" qualitative
ratings
quality_map = {3:'Low', 4: 'Low', 5:'Med', 6:'Med', 7:'High', 8:'High'}
wine_quality['Quality'] = wine_quality['quality'].map(quality_map)
## compute correlation matrix
corr = wine_quality.corr()
## Display the first 5 records of wine_quality dataset, and unique
values of quality variable
wine_quality.head()
set(wine_quality.quality)
语义和方面变量
除了在二维图中绘制关系的两个变量之外,seaborn 还可以绘制三个附加变量对两个主要变量之间的关系的影响图。 这三个变量称为语义变量。 它们被称为hue,size和style,它们充当给定绘图函数的参数。
对于hue的每个唯一值,将有一个关系图; 同样,对于style的每个唯一值,将有一个关系图。 如果中有两个唯一值hue变量(例如Yes和No),并且中有两个唯一值,则style变量(例如s和D标记),则将有2 * 2 = 4关系图(Yes & s,Yes & D,No & s,No & D组合)。 各种hue值以不同的颜色绘制,各种style值以不同的线或标记样式绘制。
同样,size变量会影响为两个主要变量绘制的点的大小。 与, Matplotlib 散点函数不同,此处,size变量范围分为多个桶,并将点分配给这些桶。 在 Matplotlib 散点函数中,每个点分别映射到size变量中的不同值。
除了这三个语义变量之外,seaborn 还允许在row和col中添加另外两个变量,其中对于的每个唯一值,行/列变量将有一个图(轴域),它将按行/列排列。 这些row和col变量称为方面变量,因为它们使我们能够了解其他方面对所绘制的两个主要变量的影响。
这些附加变量可以映射到要分析数据的各个维度,或者要分析两个变量之间的关系。 在典型的销售分析方案中,两个主要变量可以是销售额(单位或美元)或时间(天,月或季度),维度可以是业务部门,产品线,地区/ 国家/地区,销售代表,促销活动,货币等。
关系图
关系图描述了两个连续变量之间的关系。seaborn和relplot()中有一个通用的 API,用于两种类型的绘图:行和散点图绘图。 但是,这两种类型也分别具有单独的函数:lineplot()和scatterplot()。 我们可以使用带有参数的relplot()绘制线形图或散点图,或者直接使用lineplot()和scatterplot()函数。
带有一对一和一对多关系的线形图
在线形图中,观测值连接到可以自定义样式的线。x和y变量之间的关系可以是一对一的,有时也可以是一对多的。 在我们的Snack Sales数据集中,如果将每个项目的销售额与日期或期间作图,则这是一对一的关系,因为每个日期/期间和销售额对都只有一个观察值。 但是,如果我们按月销售,则每个月有 30 个观察值(销售记录),这是一对多的关系。
Seaborn 提供了多种选择来绘制这两种类型的关系。 在主要秘籍中,我们将学习一对一的关系,在“更多”部分,我们将学习一对多的关系。
准备
导入所需的包:
import matplotlib.pyplot as plt
import seaborn as sns
操作步骤
以下是绘制具有各种选项的四个折线图的步骤:
- 设置背景样式:
sns.set(style='darkgrid')
- 绘制带有标题的
Period和Smoothies销售之间的折线图:
sns.relplot(x='Period', y='Smoothies',
data=snacks_sales.query("Period < 300"), kind='line')
plt.title('line plot', size=20, color='g')
- 绘制
Period和Smoothies销售之间的折线图,并以以一周中的天作为色调:
day_order = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
'Saturday', 'Sunday']
sns.relplot(x='Period', y='Smoothies', hue='daywk',
hue_order=day_order,
data=snacks_sales.query("Period < 300"), kind='line')
plt.title('line plot with hue=daywk', size=20, color='g')
- 以
Promotion作为hue在Period和Smoothies销售之间绘制折线图:
sns.relplot(x='Period', y='Smoothies', hue='Promotion', hue_order=
["Yes", "No"],
data=snacks_sales.query("Period < 300"), kind='line')
plt.title('line plot with hue=Promotion', size=20, color='g')
- 以
Promotion作为hue,weekend作为style在Period和Smoothies销售之间绘制折线图:
sns.relplot(x='Period', y='Smoothies', hue='Promotion', hue_order=
["Yes", "No"], style='weekend',
style_order=["Y", "N"], kind='line',
data=snacks_sales.query("Period < 300"))
plt.title('line plot with hue and style', size=20, color='g')
工作原理
这是代码的说明:
sns.set(style='darkgrid')设置绘图的背景样式。 Seaborn 提供了五种预定义样式:dark,darkgrid,white,whitegrid和tickssns.relplot(x='Period', y='Smoothies', data=snacks_sales.query("Period < 300"), kind='line')绘制和两个主要变量之间的关系,它们由x和y指定:Period和Smoothies是Snacks Sales数据集中两个变量的名称Snacks Sales是输入数据集,query("Period < 300")将过滤器应用于数据集以仅绘制前 300 个观测值(行),因为绘制整个数据集太拥挤kind='line'表示绘制折线图
- 对于第二个图,我们将添加
hue='daywk'和hue_order=day_order plt.title('line plot', size=20, color='g')绘制标题,大小为 20 点,绿色。day_order = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']指定在图表上绘制星期几的顺序hue='daywk'表示绘制一周中每一天Period和Smoothies销售之间的关系,hue_order=day_order指定一周中的这一天应按[day_order列表- 对于第三张图,我们将更改
hue="Promotion"并将["Yes", "No"]映射到hue_order - 对于第四个图,我们将添加
style='weekend'和style_order=["Y", "N"]
执行上述代码后,您应该在屏幕上看到以下图表:
线形图:
线形图,色相为daywk:
以色相作为促销的线形图:
具有色相和样式的线形图:
更多
在上一节中,Period和Smoothies销售具有一对一映射。 现在让我们用替换Period到Month变量中,每个月我们有 30 个观测值(行)。 我们将再次使用Month和Smoothies销售变量绘制四幅图。 我们将使用hue和style语义变量,并将Promotion和weekend映射到它们。
以下是绘制和所需图表的代码块:
sns.relplot(x='Month', y='Smoothies', data=snacks_sales, kind='line')
plt.title('line plot', size=20, color='g')
sns.relplot(x='Month', y='Smoothies', hue='Promotion',
data=snacks_sales, kind='line',
err_style="bars", ci=68) # Standard Errors
plt.title('line plot with Error bar and hue', size=20, color='g')
sns.relplot(x='Month', y='Smoothies', hue='Promotion', style='weekend',
kind='line', ci='sd', data=snacks_sales)
plt.title('line plot with hue and style', size=20, color='g')
sns.relplot(x='Month', y='Smoothies', hue='Promotion', style='weekend',
dashes=False, markers=True,
data=snacks_sales, kind='line', ci=None)
plt.title('line plot with hue and custom style', size=20, color='g')
plt.show();
这是代码工作方式的说明:
- 在第一个图中,在之前的部分与该部分之间,唯一的区别是变量从
Period更改为Month。 由于它们与Smoothies销售的关系不同,因此该图看起来非常不同,并提供了不同的信息。 - 它基本上计算给定月份所有 30 个观测值的平均销售额,并绘制所有此类平均值的折线图。 它使用默认参数
ci=95,这意味着要计算每个平均点周围的 95% 置信区间,并绘制每个平均点周围的范围,将所有这些平均点连接为线形图,最后对这些平均点之间的范围区域进行着色 - 您还可以通过指定
estimator=None作为参数来关闭平均值和置信区间。 由于变量具有一对多关系,因此该图采用锯齿形! - 在第二个图中,通过指定
err_style='bars'和 68% 的置信区间ci=68,我们将默认线形图更改为误差图。 我们还添加hue = 'Promotion'。 - 在第三幅图中,我们使用
ci='sd'将每个月的置信区间从固定值更改为 30 个值的标准差,并添加style='weekend'。 - 在第四个图中,通过指定
dashes=False和'markers=True,我们将的默认实线和虚线的默认线型替换为默认markers。 除了markers=True之外,我们还可以指定特定的标记,例如markers=['D', 's'],以覆盖默认标记。 我们还指定ci=None以避免在平均线形图周围绘制置信区间。
执行前面的代码和之后,您应该在屏幕上看到和以下图形:
线形图:
带有误差线和色调的线形图:
具有色相和样式的线形图:
具有色相和自定义样式的线形图:
带有长格式数据集的折线图
在先前的秘籍中,我们将两个变量之间的关系绘制为单线形图,并使用其他语义变量对其进行了分析。 输入数据集具有各个项目的销售数据,例如Pies,Cakes,Cookies,Coffee和Smoothies,这些项目中的每一个都是数据集中的一列。 但是,如果要在相同的轴域/图上为这些项目中的每个项目绘制折线图以进行相对销售分析,则需要将输入数据略有不同,然后再将其传递给relplot()。
准备
当前格式的输入数据称为宽格式,因为每一项都以一列表示,从而增加了表的宽度。 我们需要创建另一种长格式的数据集,其中所有项目都合并为一列,从而增加行数或表的深度。
以下是实现此目的的代码:
## Create a long form DataFrame from wide form DF
long_sales = pd.melt(snacks_sales, var_name='Item', value_name='Sales',
id_vars=['daywk', 'weekend', 'Date', 'Promotion',
'Period', 'Month', 'Quarter'])
long_sales.shape # dimensions, number of rows and columns
long_sales.sample(n=5) # Display random 5 sample rows
这是数据集中的五个随机行的外观:
操作步骤
我们将在此秘籍中绘制两个数字。 第一个图形有四个图,第二个有一个图:
- 第一张图使用色相变量描述了每个图中所有五个项目的销售额,但每个图代表
weekend和Promotion变量的组合,它们分别指定为row和col变量:
g = sns.relplot(x='Period', y='Sales', data=long_sales, kind='line',
hue='Item', row='weekend', col='Promotion')
- 第二个图描述了每月所有项目的 30 天每日销售额,但仅包括
weekend销售,并且Promotion为ON和OFF时:
## one line for each of Items
long_sales['Day'] = pd.DatetimeIndex(long_sales['Date']).day
sns.relplot(x='Day', y='Sales', hue='Promotion',
data=long_sales.query("weekend =='Y'"), kind='line',
units="Item", estimator=None, lw=1, height=6, aspect=2);
工作原理
这是前面代码的解释:
x,y,data,kind和hue参数与我们在前面的秘籍中看到的参数完全相同row='weekend'指定对于weekend的每个唯一值,沿图的行绘制单独的轴域col='Promotion'指定对于Promotion的每个唯一值,沿图的列绘制单独的轴域- 当同时指定了
row和col变量时,它将使用两者的组合来绘制网格
结果图如下所示:
对于第二个图,我们首先定义一个派生变量Day,以存储每个观察值/行的当月值并将其添加到输入数据集中。 一年中的每一天都会代表一年中的每个月进行 12 次销售观察。 我们将在此图中绘制按日销售:
data=long_sales.query("weekend =='Y'")限制仅在周末绘制数据。units="Item"指定为Item的每个唯一值绘制折线图。estimator=None关闭每个折线图的计算和绘图平均值以及置信区间lw=1指定要绘制的线的宽度height=6和aspect=2指定图形的大小,高度为 6 英寸,宽度为 12 英寸(高度的两倍)
结果图如下。 它的一个问题是不清楚哪个线形图属于哪个项目! 目前,在这种情况下,它不允许我们绘制标签:
散点图
散点图将两个变量之间的关系绘制为单个点,而不相互连接。 它有助于可视化这些点如何在 x 和 y 轴上分布,以发现数据中是否存在任何模式或簇。 我们将使用与上一节相同的Snack Sales数据集,并在主要部分中使用相同的语义变量,并在中使用row和col变量“更多”部分。
准备
导入所需的库并将背景样式设置为dark:
import matplotlib.pyplot as plt
import seaborn as sns
操作步骤
- 在
Smoothies销售和Period之间绘制散点图:
sns.relplot(x='Period', y='Smoothies', data=snacks_sales,
kind='scatter')
plt.title('scatter plot', size=20, color='g')
- 添加
hue = 'Promotion':
sns.relplot(x='Period', y='Smoothies', hue='Promotion',
data=snacks_sales)
plt.title('scatter plot with hue', size=20, color='g')
- 添加
style = 'weekend':
sns.relplot(x='Period', y='Smoothies', hue='Promotion',
style='weekend', markers=['^', 'D'],
data=snacks_sales)
plt.title('scatter plot with hue and style', size=20, color='g')
- 添加
size = 'Cookies':
sns.relplot(x='Period', y='Smoothies', hue='Promotion',
style='weekend', size='Cookies',
markers=['^', 'D'],data=snacks_sales)
plt.title('scatter plot with hue, size and style', size=20,
color='g');
工作原理
lineplot()和scatterplot()之间的唯一区别是将kind='line'更改为kind='scatter'。 在relplot()中,默认为kind='scatter',因此您可以省略此参数,就像我们在此处绘制的一些图所示。
所有,其他参数与前面的秘籍中的,完全相同。
这是绘图的样子:
散点图:
带有色相的散点图:
具有色相和样式的散点图:
具有色相,大小和样式的散点图:
更多
在本节中,我们将使用row和col参数以及hue绘制相同的数据。
这是此代码:
day_order = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
'Saturday', 'Sunday']
sns.relplot(x='Period', y='Smoothies', hue='Promotion', col='daywk',
col_wrap=3, col_order=day_order, data=snacks_sales,
height=3)
sns.relplot(x='Period', y='Smoothies', col='daywk',
col_order=day_order, row='Promotion', row_order=['Yes',
'No'], data=snacks_sales, height=3)
plt.show();
col_wrap=3指定仅绘制三列,然后将其包装到下一行。 使用此选项时,不能使用row参数。
您应该在屏幕上看到和下图:
与hue_order和style_order相似,我们也可以指定row_order和col_order。
结果图如下:
类别图
当要绘制的两个变量之一是分类的,而不是连续的时,则使用类别图。 Seaborn 增强了 Matplotlib 提供的和类别图中的一些,并且还添加了一些其他图。 在本节中,我们将介绍五组这样的绘图。
Seaborn 提供了一个通用 API catplot()来涵盖所有此类图。 这使您更容易熟悉一组通用参数,可以传递这些参数来绘制所有类型的类别图。 但是,每个不同的函数都可以直接使用,有时其中一些函数可能提供并非所有类型的绘图都通用的独特功能。 请参考这个页面上每个特定图的文档。
条带和群体图
由于其中一个变量是分类变量,因此,给定分类变量值的和其他变量的所有值都落在一条直线上,该直线具有许多重叠点,这使其难以可视化。 条带图和群体图允许将这些点绘制成稍微偏离直线,避免基于给定参数的重叠。
准备
导入所需的库,将背景样式设置为ticks,并在以 Matplotlib 格式指定时启用color_codes映射为seaborn颜色:
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(style="ticks", color_codes=True)
操作步骤
- 用
jitter=0.05和hue='Promotion'绘制星期几Cookies的销售条形图:
day_order = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
'Saturday', 'Sunday']
sns.catplot(x='daywk',y='Cookies', data=snacks_sales,
hue='Promotion', order=day_order, jitter=0.05, height=4,
aspect=2, kind='strip')
plt.title('stripplot with jitter=0.05', size=20, color='g')
- 使用,默认
jitter和指定的调色板,绘制星期四(星期四除外)Cookies的销售条形图:
sns.catplot(x='daywk',y='Cookies', data=snacks_sales.query("daywk !=
'Thursday'"), order=['Monday', 'Tuesday', 'Wednesday',
'Friday', 'Saturday', 'Sunday'],palette='Set1',
height=4, aspect=2); # jitter=False plots all the points
on one line similar to plt
plt.title('stripplot with default jitter', size=20, color='g')
- 绘制
Cookies和一周中hue = 'Promotion'的群销售图:
sns.catplot(x='daywk',y='Cookies', data=snacks_sales,
order=day_order, hue='Promotion',
kind='swarm',height=4, aspect=2)
plt.title('swarmplot', size=20, color='g');
工作原理
这是前面代码的解释:
order=day_order指定在轴域上绘制,分类变量的唯一值的顺序。jitter=0.05指定要应用的抖动量; 的值越大,的值越长直线范围。kind='strip'指定图的类型,在这种情况下为stripplot()。 但是,这是catplot()的默认类型,因此也可以省略。- 如果要并排绘制
hue变量值,而不是在同一条带上同时显示两种颜色,则可以传递和dodge=True参数。 对于stripplot(),默认为dodge=False,这是我们在此处使用的内容。 data=snacks_sales.query("daywk != 'Thursday'")过滤输入数据以排除Thursday的所有观测值,因此该图仅包括一周中的剩余天数。palette='Set1'指定要应用的调色板。 它类似于 Matplotlib 的cmap。 我们也可以在此处使用 Matplotlib 提供的cmap选项。- 我们将默认
jitter用于第二个绘图。 默认值不是jitter的固定值,而是根据输入数据分布而变化。 - 我们还可以通过指定
jitter=False来关闭抖动,在这种情况下,其输出将类似于 Matplotlib 的输出。 - 第三个图
kind='swarm'指定要绘制的游泳图。 在这里,它使用不同的算法在线上分布点,以确保根本没有重叠的点:
箱形图和 Boxn 图
boxplot()与我们在 Matplotlib 中看到的类似,boxnplot()是 Seaborn 的扩展,旨在提供有关该关系的更多详细信息。
boxplot()提供中值(框内的线),第一个(框的底部)和第三个四分位数(框的顶部),顶部和底部的 1.5 IQR(1.5 倍的框的大小(垂直图的高度,水平图的宽度))位置的胡须,以及胡须以外的异常值的详细信息。 几百个观察说,对于大多数情况来说和数据集的大小很小,这已经足够了。
但是,当数据集很大时,则无法对和尾端提供足够的见解。boxnplot()通过提供多个四分位数覆盖两端的尾端来解决boxplot()的这一局限性。 有关此的更多详细信息,请参阅此处的论文。
准备
导入所需的库,将背景样式设置为ticks,并在以 Matplotlib 格式指定时,将color_codes映射为深浅的颜色:
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(style="ticks", color_codes=True)
操作步骤
在这里,我们将使用长格式数据集并绘制所有商品的销售情况:
- 绘制
boxplot(),其中包含以下各项的销售额:
sns.catplot(x='Item', y='Sales', data=long_sales, kind='box',
height=4, aspect=2);
- 为第二个图添加
hue=Promotion:
sns.catplot(x='Item', y='Sales', data=long_sales, kind='box',
hue='Promotion', height=4, aspect=2);
- 将色调更改为
hue=weekend:
sns.catplot(x='daywk', y='Sales', data=long_sales, kind='box',
hue='weekend', order=day_order, height=4, aspect=2);
- 用
boxnplot()重复和最后三步:
sns.catplot(x='Item', y='Sales', data=long_sales, kind='boxen',
height=4, aspect=2);
sns.catplot(x='Item', y='Sales', data=long_sales, kind='boxen',
hue='Promotion', height=4, aspect=2);
sns.catplot(x='Sales', y='daywk', data=long_sales, kind='boxen',
hue='weekend',
order=day_order, height=4, aspect=2);
工作原理
这是前面代码的解释:
kind='box'指定它是boxplot()。dodge=True是boxplot()和boxnplot()的默认值,因此默认情况下,将为和色调变量的每个唯一值绘制一个单独的图。 如果要在同一个箱图上绘制两个图,则必须传递dodge=False参数。kind='boxen'指定绘制一个箱形图。
执行上述代码后,您应该在屏幕上看到以下图表:
条形图和计数图
barplot()与我们在 Matplotlib 中看到的类似,但是countplot()是 seaborn 的扩展。barplot()中条形的高度代表给定类别的所有观测值的平均值,而countplot()中,条形高度代表给定类别的观察数。
准备
导入所需的库,将背景样式设置为ticks,并在以 Matplotlib 格式指定时,将color_codes映射为深浅的颜色:
import matplotlib.pyplot as plt
import seaborn as sns
from numpy import median
sns.set(style="ticks", color_codes=True)
操作步骤
我们将使用各种不同的选项绘制四个条形图和三个计数图:
- 使用,长数据格式的输入数据绘制
barplot(),并在顶部用实际值标注条:
plt.figure(figsize=(9,4))
b = sns.barplot(x='Item', y='Sales', data=long_sales, estimator=sum,
palette='husl')
b.set(yscale='log', ylim=[50000, 1000000])
sns.despine()
for bar in b.patches:
b.annotate("{:,}".format(bar.get_height()),
(bar.get_x()+bar.get_width()/2.,bar.get_height()),
ha='center',va='center',xytext=
(0,10),textcoords='offset points',
color='b', weight='bold')
plt.title('Bar Plot: Long Data Format,value annotation &
estimator=sum', size=15, color='g', weight='bold')
- 使用全数据格式的输入数据绘制
barplot(),以绘制所有数字变量:
sns.catplot(data=snacks_sales, kind='bar', height=4, aspect=2, #
wide form
order=['Cakes', 'Pies', 'Cookies', 'Smoothies',
'Coffee', 'weekday', 'Period'],
palette="Set1");
plt.title('Bar Plot: Wide Data Format,Plots all numerical
variables', size=15, color='g', weight='bold')
- 使用长数据格式,估计量等于中位数和自定义调色板绘制
barplot():
sns.catplot(x='Item', y='Sales', data=long_sales, kind='bar',
hue='Promotion', hue_order=['Yes','No'], palette={"Yes":
"r", "No": "indigo"},
estimator=median, capsize=0.25, height=4, aspect=2);
plt.title('Bar Plot: Long Data Format, estimator=median and custom
palette', size=15, color='g', weight='bold')
- 用
estimator=len/count,自定义误差宽度和颜色绘制barplot():
day_order = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
'Saturday', 'Sunday']
sns.catplot(x='daywk', y='Sales', data=long_sales, kind='bar',
hue='Promotion', ci='sd',
estimator=len, capsize=0.25, errcolor='m', errwidth=5,
hue_order=['Yes','No'], palette="muted",
order=day_order, height=4, aspect=2);
plt.title('Bar Plot, estimator=len(count), errwidth=5, errcolor=m',
size=15, color='g', weight='bold')
- 绘制一个
countplot(),其中包含所有项目的销售额:
sns.catplot(x='Item', data=long_sales, kind='count', height=4,
aspect=2); # long form data frame
plt.title('Count Plot: Sales by Item', size=15, color='g',
weight='bold')
- 使用
hue和自定义调色板绘制countplot():
sns.catplot(x='Item', data=long_sales, kind='count',
hue='Promotion', hue_order=['Yes','No'], palette={"Yes":
"r", "No": "indigo"}, height=4, aspect=2);
plt.title('Count Plot, hue=Promotion, custom palette', size=15,
color='g', weight='bold')
- 绘制
countplot(),按星期几销售:
day_order = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
'Saturday', 'Sunday']
sns.catplot(x='daywk', data=long_sales, kind='count',
hue='Promotion', hue_order=['Yes','No'], palette="Set2",
order=day_order, height=4, aspect=2);
plt.title('Count Plot: Sales by day of the week', size=15,
color='g', weight='bold');
工作原理
这是前面代码的解释。 这是第一个绘图:
catplot()和kind='bar'不能灵活地捕获单个条形图,因此无法在每个条形图的顶部绘制值。 因此,对于第一个图,我们使用barplot(),它类似于的 Matplotlib 条形图b = sns.barplot(x='Item', y='Sales', data=long_sales, estimator=sum, palette='husl')绘制条形图:estimator=sum指定指定给定项目的所有观测值之和,而不是默认平均值palette='husl'指定要使用的调色板
b.set(yscale='log', ylim=[50000, 1000000])在 y 轴上设置对数刻度并将限制设置为给定限制。sns.despine()使和的上轴线和右轴线不可见。 如果要使左轴和底轴也不可见,则可以传递参数left=True和right=True。for bar in b.patches:是一个for循环,可捕获每个条形并在其顶部绘制值。 和与我们在第 2 章和“基本绘图入门”中所做的相同,对于是 Matplotlib 条形图。plt.title('Bar Plot: Long Data Format,value annotation & estimator=sum', size=15, color='g', weight='bold')绘制图表标题。
这是第二个绘图:
- 我们直接传递宽格式数据集,而没有像到目前为止一样提供
x和y变量。 在这种情况下,默认情况下会绘制输入数据集中每个数字变量的条形图。 - 但是,我们可以通过不在顺序列表中指定这些变量来防止某些数字列被绘制。
order=['Cakes', 'Pies', 'Cookies', 'Smoothies', 'Coffee', 'Period']:除实际项目外,我们顺序列表中仅包含Period。 因此,即使它们是数字变量,也不会绘制weekday,Month和Quarter变量。palette="Set1"设置为预定义的调色板Set1。
这是第三个绘图:
- 我们返回长数据格式并指定
x和y数据变量。 hue='Promotion'指定使用不同的颜色映射为Promotion的每个唯一值绘制条形图。hue_order=['Yes','No']指定绘制Promotion条的顺序。palette={"Yes": "r", "No": "indigo"}指定自定义调色板字典。estimator=median指定用于汇总给定项目的观察值的统计信息。 默认统计信息是平均值; 在这里,我们用中位数覆盖它。 在此数据集中,所有项目的均值和中位数彼此非常接近,因此我们可能无法观察到条形图中的差异。 某些函数sum和len在核心 Python 中可用,因此不需要导入它们,而median在 Python 中不可用,因此我们需要从 NumPy 导入。capsize=0.25在误差栏的顶部和底部指定和误差栏帽的宽度。
这是第四个绘图:
estimator=len指定将汇总统计信息的长度(观察数)用作。ci='sd'指定对置信区间的使用标准差,而不是固定百分比值。errcolor='m'将误差栏的颜色指定为洋红色。errwidth=5指定彩条线的宽度。
这是第五个绘图:
kind='count'指定应绘制一个计数图。- 在这里,条形的高度是-每个项目类别中观察值的计数。 在这种情况下,所有项目的计数均相同。
这是第六个图:
- 我们加上
hue="Promotion",因此Promotion的两个值的计数不同。 - 我们像第三张图一样使用自定义调色板
这是偶数图:
- 将 x 轴的
Item替换为daywk。 palette="Set2"设置另一个预定义的调色板。
执行上述代码后,您应该在屏幕上的以下七个图上看到和:
提琴图
Seaborn 扩展了 Matplotlib 提供的提琴图功能,以在, 提琴图中包含不同的图。 与仅显示摘要统计信息的boxplot不同,提琴图甚至显示数据的分布。
准备
导入所需的库,将背景样式设置为ticks,并启用color_codes,以 Matplotlib 格式指定时将其映射为 Seaborn 颜色:
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(style="ticks", color_codes=True)
操作步骤
我们将在此处绘制四个带有不同选项的提琴图:
- 在 x 轴域上绘制销量,在 y 轴域上绘制物品:
sns.catplot(x='Sales', y='Item', data=long_sales, kind='violin',
height=6, aspect=1)
plt.title('1\. Horizontal Violin Plot', size=15, color='g',
weight='bold')
- 在 x 轴域上绘制物品并在 y 轴域上绘制销量,添加
hue='Promotion',然后在提琴图的两侧分别填充不同的颜色:
sns.catplot(x='Item', y='Sales', data=long_sales, kind='violin',
hue='Promotion',
hue_order=["Yes", "No"], split=True, height=4, aspect=2)
plt.title('2\. Vertical Violin Plot, hue=Promotion, split=True',
size=15, color='g', weight='bold')
- 用
hue='Promotion'绘制垂直提琴图,并用数据填充提琴的两侧:
day_order = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
'Saturday', 'Sunday']
sns.catplot(x='daywk', y='Sales', data=long_sales, kind='violin',
order=day_order, hue='Promotion',
hue_order=["Yes", "No"], split=True, inner="stick",
palette="pastel",height=4, aspect=2)
plt.title('3\. Violin Plot, hue=Promotion, split=True, inner=stick',
size=15, color='g', weight='bold')
- 用
hue='Promotion'绘制垂直提琴图,用不同的颜色填充侧面,然后覆盖群图:
g = sns.catplot(x='daywk', y='Sales', data=long_sales,
kind='violin', order=day_order, hue='Promotion',
hue_order=["Yes", "No"], split=True, inner=None,
palette="pastel", height=4, aspect=2)
sns.catplot(x='daywk',y='Sales',
data=long_sales[long_sales['Period'] < 50], order=day_order,
color="k", size=3, kind='swarm',height=4, aspect=2, ax=g.ax)
g.ax.set_title('4\. Violin Plot with overlay of swarm plot', size=15,
color='g', weight='bold');
plt.axis('off'); # remove unwanted empty axes
工作原理
这是前面代码的解释。
这是第一个绘图:
x='Sales' and y='Item'指定类别变量在 y 轴上,连续变量在 x 轴上,生成水平图kind='violin'指定它是提琴图height=6将图的高度指定为6英寸aspect=1表示,图的宽度为,与相同,高度
这是第二个图:
x='Item', y='Sales'指定规则的垂直图。hue='Promotion'将变量指定为Promotion。hue_order=["Yes", "No"]指定绘制Promotion值的顺序。split=True仅在hue变量为二进制时适用,并指定提琴的每一侧应填充不同的颜色,代表的值hue变量。
这是第三个图:
- 将
Item变量替换为 x 轴上的daywk变量,并提供绘制日期的顺序。 inner="stick"指定绘制棒状线,代表和Promotion变量的两个不同值,代表提琴每侧的数据分布; 这仅在split=True时适用,而在,hue变量为二进制时才适用。palette="pastel"指定要使用的预定义调色板。
这是我们的绘图:
kind='violin'指定绘制提琴图。inner=None指定除了基于hue的颜色映射外,不在提琴的任何一侧绘制任何内容。data=long_sales[long_sales['Period'] < 50]将绘图限制为仅 50 个观测值,以避免混乱。kind='swarm'指定violinplot顶部的覆盖图为swarmplot。ax=g.ax指定叠加图的轴域,与绘制violinplot的轴域相同。
执行上述代码后,您应该在屏幕上看到以下四个图:
点图
条带图和群图以不重叠的方式绘制属于特定类别的所有点。box,boxn和violin图描绘了各种类别的一组点的摘要统计量; 同样,bar和count使用某些统计指标绘制汇总,并相应绘制条形图。 最后,point图将聚合度量描述为图形中的一个点,各个类别的所有此类点均用线连接。
准备
导入所需的库,将背景样式设置为ticks,并以 Matplotlib 格式指定时,将color_codes映射为seaborn颜色。 :
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(style="ticks", color_codes=True)
操作步骤
我们将用不同的选项绘制四个点图:
- 绘制一个
pointplot()和宽表单数据集,以绘制所有在顺序列表中列出的数字变量:
sns.catplot(data=snacks_sales, kind='point', ci=99.99, capsize=0.25,
height=4, aspect=2, order=['Cakes', 'Pies', 'Cookies',
'Smoothies', 'Coffee', 'weekday', 'Period'])
plt.title('1\. Point Plot with wide form dataset', size=15,
color='g', weight='bold');
- 使用长数据集绘制此
pointplot(),以s指定标记并将置信区间为的标准差绘制i变量。
sns.catplot(x='Item', y='Sales', data=long_sales, kind='point',
markers='D', ci='sd', height=4, aspect=2) # long form
data frame
plt.title('2\. Point Plot with diamond marker and std as ci',
size=15, color='g', weight='bold');
- 使用其他
hue和col变量以及自定义调色板来绘制此pointplot():
sns.catplot(x='Item', y='Sales', data=long_sales, kind='point',
hue='Promotion', hue_order=['Yes','No'], palette={"Yes":
"r", "No": "indigo"},
markers=["^", "o"], linestyles=["-", "--"], ci=None,
col='daywk', col_wrap=3,
height=4, aspect=2, scale=1.5)
plt.suptitle("3\. Point Plot, hue=Promotion, col='daywk'", size=15,
color='g', weight='bold')
plt.tight_layout(pad=5,w_pad=0.25, h_pad=0.25);
- 以
pointplot()和色相来表示每日销售量,并确保和线形图对于两个Promotion的不同值不重叠:
sns.catplot(x='daywk', y='Sales', data=long_sales, kind='point',
hue='Promotion', dodge=True,
hue_order=['Yes','No'], palette="Set2", order=day_order,
height=4, aspect=2)
plt.title('4\. Point Plot of day wise sales with hue and dodge',
size=15, color='g', weight='bold');
工作原理
这是前面代码的解释。
这是第一个绘图:
kind='point'指定它是pointplot()。ci=99.99指定置信区间。capsize=0.25指定误差条顶部的盖子宽度。order=['Cakes', 'Pies', 'Cookies', 'Smoothies', 'Coffee', 'weekday', 'Period'])指定轴上项目的顺序。
这是第二个图:
markers='D'指定使用菱形标记代替圆圈。ci='sd'指定对使用标准差作为置信区间。
这是第三个图:
hue='Promotion'使用变量Promotion指定色调。hue_order=['Yes','No']是绘制色调值的顺序。palette={"Yes": "r", "No": "indigo"}是自定义调色板。markers=["^", "o"]使用这些标记为的每个唯一值指定Promotion变量。linestyles=["-", "--"]是每个折线图的线条样式。ci=None指定不绘制的置信区间范围。col='daywk'使用变量指定daywk绘制列。col_wrap=3指定每行仅绘制三个图,然后将下一行包装到中。scale=1.5在默认大小上指定绘图上对象大小的比例因子。plt.suptitle()打印整个图形的标题。plt.tight_layout(pad=5,w_pad=0.25, h_pad=0.25);调整绘图之间的空间,并在图形顶部留出足够的空间,以使和标题完全合适。
这是我们的图:
- 它类似于第三图的,但不使用
col变量并应用dodge=True,因此将Promotion的两个唯一值的图分开设置,而不是像第三幅图一样。
执行上述代码后,您应该在屏幕上看到以下四个图:
分布图
分布图用于可视化数据的概率分布。 Seaborn 提供了三个函数:distplot(),kdeplot()和rugplot()。
通过传递适当的参数,distplot()可用于核密度估计(KDE)和地毯分布。 但是,distplot()限于单变量分布,而kdeplot()也允许双变量分布。 因此,当需要双变量分布时,可以使用kdeplot(),对于单变量分布,可以使用distplot()。
distplot()
我们将绘制三个具有不同选项的不同分布图,以展示其大多数功能。
准备
导入所需的库,将背景样式设置为white,并在以 Matplotlib 格式指定时,将color_codes映射为深浅的颜色:
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.stats import norm, pareto, gamma
sns.set(style="whitegrid", color_codes=True)
scipy.stats是一个包含各种统计函数的科学 Python 库,norm,pareto和gamma是不同类型的概率分布函数。 我们将使用它们来拟合和给定的数据集,以查看哪种分布非常适合该数据。
操作步骤
以下是绘制和所需图的步骤:
- 用直方图,KDE 和
rugplot绘制销售Coffee的分布:
sns.distplot(snacks_sales.Coffee, color='g', rug=True, rug_kws=
{"color": 'm', "height": 0.1})
plt.title('1\. Distribution Plot of Coffee Sales with rug=True',
size=15, color='g', weight='bold')
plt.show();
- 使用步骤类型直方图,带阴影的 KDE 和图例绘制曲奇销售的水平分布:
sns.distplot(snacks_sales.Cookies, vertical=True,
hist_kws={"histtype": "step", "linewidth": 3, "alpha":
1, "color": "indigo", "label": "Histogram"},
kde_kws={"shade": True, "color": "orange", "lw": 3,
"label": "KDE"})
plt.title('2\. Horizontal Distribution Plot of Cookies Sales',
size=15, color='g', weight='bold')
plt.show();
- 绘制销售的分布,并拟合三种不同的分布,以检查哪种分布最适合此数据:
ax = sns.distplot(snacks_sales.Smoothies, fit=norm, kde=False,
rug=True, color='b',
fit_kws={"color": "b"}, label='normal')
sns.distplot(snacks_sales.Smoothies, hist=False, fit=pareto,
kde=False, rug=True, color='g', label='pareto',
fit_kws={"color": "g"}, ax=ax)
sns.distplot(snacks_sales.Smoothies, hist=False, fit=gamma,
kde=False, color='r', label='gamma',
fit_kws={"color": "r"}, ax=ax)
ax.legend()
plt.title('3\. Distribution Plot - 3 different distribution
functions', size=15, color='g', weight='bold')
plt.show();
工作原理
这是前面代码的解释:
这是第一个绘图:
sns.distplot(snacks_sales.Coffee, color='g', rug=True, rug_kws={"color": 'm', "height": 0.1})图。 这是必需的分布图。snacks_sales.Coffee是要绘制其分布的咖啡销售数据。color='g'指定默认情况下绘制的直方图和 KDE 图的颜色为绿色。- 如果要关闭直方图或 KDE 图,请传递参数
hist=False和kde=False。 rug=True指定是否应在该分布图上绘制地毯图。 默认选项是False,因此未绘制。rug_kws={"color": 'm', "height": 0.1}是用于格式化地毯图的关键字字典。 在这里,我们使用了洋红色,在地毯图中,木棒的高度为o.1。plt.show()在屏幕上显示绘图,因此后续绘图不会在第一个绘图的顶部重叠。
这是第二个图:
vertical=True指定该图应在垂直轴域上绘制,这表示水平直方图。 默认选项为False,在这种情况下,它会绘制垂直直方图,如在第一个图中所示。hist_kws={"histtype": "step", "linewidth": 3, "alpha": 0.7, "color": "indigo", "label": "Histogram"}是用于绘制直方图的参数的直方图关键字字典:"histtype": "step"指定楼梯直方图,而不是规则的平滑坡道。"linewidth": 3表示直方图的线宽为三点。"alpha": 0.7指定直方图行的透明度级别。"color": "indigo"指定直方图的颜色为靛蓝色。"label": "Histogram"是出现在图例上的标签。
kde_kws={"shade": True, "color": "orange", "lw": 3, "label": "KDE"})是用于绘制 KDE 绘图的参数的关键字字典:"shade": True指定在 KDE 图下的区域应加阴影。"color": "orange"指定用于 KDE 图的颜色,并在 KDE 曲线下的区域上加阴影。 尽管我们指定了一种颜色,但它的 KDE 曲线和曲线下的阴影区域使用略有不同的阴影来区分这两种颜色。"lw": 3指定要绘制的线的宽度。"label": "KDE"是出现在图例上的标签。
这是第三个图:
- 在该图中,我们为同一数据拟合了三条不同的曲线,以检查哪一条最合适。 实际上,存在许多连续和离散的分布。 根据数据的性质,我们在选择最佳分布之前先尝试这些分布。 在
distplot()中使用它们之前,我们需要导入适当的包(scipy.stats是一个很好的来源)以加载这些分发函数。 fit=norm指定适合正态分布; 同样,fit=pareto和fit=gamma指定pareto和gamma分布函数以适合我们拥有的数据。kde=False指定不绘制 KDE 曲线,因为我们正在拟合其他分布。 如果我们想将 KDE 曲线与其他分布进行比较,我们也可以保留它。rug=True指定我们也应该为此数据绘制rugplot()。fit_kws={"color": "b"}是用于拟合给定分布函数的关键字字典。 它仅指定要用于分布曲线的颜色。
执行上述代码后,您应该在以下三个图中看到:
kdeplot()
KDE 是一种将分布函数拟合到给定数据集的非参数方法。 因此,对于给定的单变量(单变量)或双变量(两个变量)数据,kdeplot()拟合并绘制 KDE 分布曲线。
准备
导入所需的库,将背景样式设置为white,并启用color_codes,以 Matplotlib 格式指定时将其映射为 Seaborn 颜色:
import matplotlib.pyplot as plt
import seaborn as sns
操作步骤
我们将绘制两个二元 KDE 图。 在第二个图中,我们将在相同的轴域上绘制两个具有不同变量集的 KDE 图,以进行比较:
- 用等高线和颜色条绘制双变量 KDE 图:
sns.kdeplot(snacks_sales.Smoothies, snacks_sales.Pies, kernel='epa',
n_levels=25, cmap='Reds', cbar=True)
plt.title('1\. Bivariate KDE Plot', size=15, color='g',
weight='bold');
plt.show();
- 用阴影区域绘制两组变量的双变量 KDE 图:
Cookies_temp = snacks_sales.Cookies + 500
ax=sns.kdeplot(snacks_sales.Period, snacks_sales.Coffee,
kernel='gau',shade=True, shade_lowest=False,
cmap='Purples_d')
sns.kdeplot(snacks_sales.Period, Cookies_temp, kernel='cos',
shade=True, shade_lowest=False, cmap='Blues')
ax.set_ylabel('Sales')
ax.text(0, 1400, 'Cookies', color='b', weight='bold')
ax.text(0, 650, 'Coffee', color='purple', weight='bold')
plt.title('2\. Bivariate KDE Plot - 2 sets of variables', size=15,
color='g', weight='bold')
plt.show();
工作原理
这是代码的说明。
这是第一个绘图:
snacks_sales.Smoothies和snacks_sales.Pies是要绘制的变量。kernel='epa'指定要用于适合 KDE 的内核方法(Epanechnikov)。 其他可用选项包括gau(高斯/正态),cos(余弦),biw(双权),triw(三权)和tri(三角形)。 有关更多详细信息,请参阅这里。n_levels=25指定要绘制的轮廓数量。cmap='Reds'指定要使用的颜色表。cbar=True指定绘制颜色条。
这是第二个图:
Cookies_temp = snacks_sales.Cookies + 500将所有观测值增加 500,这样这些值就不会与我们将在同一轴域上绘制的其他变量值重叠。ax=sns.kdeplot(snacks_sales.Period, snacks_sales.Coffee, kernel='gau',shade=True, shade_lowest=False, cmap='Purples_d')在ax轴域上绘制第一个 KDE 图。kernel='gau',使用高斯核方法shade=True填充轮廓内的区域。shade_lowest=False仅适用于shade=True,仅适用于二元 KDE 图。 它迫使它不填充最外轮廓,该轮廓覆盖轮廓外轴域的整个区域。 如果我们不将其设置为false,则可能会看到整个轴域的区域都填充了最外面轮廓的颜色。ax.set_ylabel('Sales')覆盖从数据变量名称中拾取的默认 y 轴标签。ax.text(0, 1400, 'Cookies', color='b', weight='bold')和ax.text(0, 650, 'Coffee', color='purple', weight='bold')插入 KDE 图的标签:kdeplot()中提供的'label'选项仅适用于单变量图。 因此,我们在此处使用了text选项。
执行上述代码后,您应该在屏幕上看到以下两个图:
| |
|
回归图
回归图有助于将二维数据拟合为线性或多项式曲线。 这有助于可视化两个变量之间的关系,以了解它与 n 的线性或多项式拟合的紧密程度。 Seaborn 为此提供了三个函数:regplot(),residplot()和lmplot()。regplot()和lmplot()都具有将二维数据拟合为 n 的线性或多项式的相同目的,但是regplot()是轴域级函数,而lmplot()是图形级函数,使它能够使用row和col语义变量在单个图形中绘制多个回归图。residplot()帮助拟合曲线并绘制残差以了解拟合的质量。
regplot()和residplot()
我们将绘制两个回归图和一个残差图以演示这些函数中可用的各种选项。
准备
导入所需的库,将背景样式设置为dark,并在以 Matplotlib 格式指定时,将color_codes映射为深浅的颜色:
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.stats import pearsonr
sns.set(style="dark", color_codes=True)
操作步骤
以下是绘制和所需图的步骤:
- 绘制线性回归图,并以 R 方和 p 值标注:
R, p = pearsonr(wine_quality['fixed acidity'], wine_quality.pH)
g1 = sns.regplot(x='fixed acidity', y='pH', data=wine_quality,
truncate=True, ci=99,
marker='D', scatter_kws={'color': 'r'});
textstr =
'$\mathrm{pearson}\hspace{0.5}\mathrm{R}^2=%.2f$\n$\mathrm{pval}=%.
2e$' % (R**2, p)
props = dict(boxstyle='round', facecolor='wheat', alpha=0.5)
g1.text(0.55, 0.95, textstr, transform=ax.transAxes, fontsize=14,
va='top', bbox=props)
plt.title('1\. Linear Regression', size=15, color='g', weight='bold')
- 绘制
2阶多项式回归曲线:
g2 = sns.regplot(x='fixed acidity', y='pH', data=wine_quality,
order=2, ci=None,
marker='s', scatter_kws={'color': 'skyblue'},
line_kws={'color': 'red'});
plt.title('2\. Non Linear Regression of order 2', size=15, color='g',
weight='bold')
- 绘制逻辑回归曲线:
wine_quality['Q'] = wine_quality['Quality'].map({'Low': 0, 'Med': 0,
'High':1})
g2 = sns.regplot(x='fixed acidity', y='Q', logistic=True,
n_boot=750, y_jitter=.03, data=wine_quality,
line_kws={'color': 'r'})
plt.show();
- 绘制残差图:
g3 = sns.residplot(x='fixed acidity', y='density', order=2,
data=wine_quality, scatter_kws={'color': 'b',
'alpha': 0.5});
plt.show();
工作原理
这是代码的说明。
这是第一个绘图:
R, p = pearsonr(wine_quality['fixed acidity'], wine_quality.pH)计算给定数据分布的和的R和p值。 R 方和 p 值表示数据拟合的质量。g1=sns.regplot()绘制了回归曲线以及和原始数据点的散布图:truncate=True指定仅在可用数据点之前拟合曲线。 默认设置是将其扩展到轴域的两端。ci=99指定在线性曲线的周围绘制 99% 的置信区间。marker='D'以菱形绘制点,而不是默认圆。scatter_kws={'color': 'r'}是散点图关键字字典,具有要使用的属性。 用红色绘制点。- 富文本格式的
textstr指定要在曲线上绘制的文本。 props指定要在曲线上绘制的文本字符串周围的框的属性。g1.text()在指定位置的打印文本。
这是第二个图:
g2 = sns.regplot()绘制散点图,具有二阶多项式。order=2指定拟合二阶多项式。ci=None不在绘制拟合曲线周围的置信区间。marker='s'以正方形绘制点,而不是默认圆。scatter_kws={'color': 'skyblue'}为散点指定的颜色。line_kws={'color': 'red'}指定回归线的颜色。
这是第三个图:
wine_quality['Q'] = wine_quality['Quality'].map({'Low': 0, 'Med': 0, 'High':1})通过将Low和Med映射到0以及将High映射到1,得出仅具有二进制值'0'或'1'的新质量变量。 这是拟合逻辑回归曲线所必需的。g3 = sns.regplot()绘制散点图并拟合逻辑回归曲线:logistic=True指定拟合逻辑回归曲线。n_boot=750指定用于估计和置信区间的重采样次数。y_jitter=.03指定要添加的偏差量,以使点不会重叠太多。 这仅影响可视化,并在拟合曲线之后和绘制之前添加。line_kws={'color': 'r'},用红色绘制拟合曲线。
这是我们的绘图:
g4 = sns.residplot()绘制残差的散点图,并在0残差周围绘制一条虚线。scatter_kws={'color': 'b', 'alpha': 0.5}绘制蓝色的残留点,透明度为0.5。
执行和之前的代码后,您应该在屏幕上看到以下四个图:
lmplot()
我们将绘制三个具有不同选项的绘图。 对于第一个,我们将使用hue变量,对于,将第二个使用col变量以及参数回归模型, 对于第三个变量,我们将col变量与非参数回归模型一起使用。
准备
导入所需的库,将背景样式设置为dark,并在以 Matplotlib 格式指定时,将color_codes映射为深浅的颜色:
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(style="dark", color_codes=True)
操作步骤
以下是绘制和所需图的步骤:
- 使用
Quality作为变量hue绘制线性回归图:
g1 = sns.lmplot(x='fixed acidity', y='pH', hue='Quality', hue_order=
['Low', 'Med', 'High'], logx=True,
data=wine_quality, height=4, aspect=2, ci=None)
- 使用
Quality作为变量col绘制参数回归图,并自定义标签,刻度和轴限制:
g2 = sns.lmplot(x='fixed acidity', y='pH', data=wine_quality, ci=99,
col='Quality', col_order=['Low', 'Med', 'High'],
height=3, robust=True, scatter_kws={'color': 'g'})
g2 = g2.set_axis_labels("Fixed Acidity", "pH")
g2.set(xlim=(0, 20), ylim=(2.4, 4.0), xticks=[5, 10, 15, 20],
yticks=[2.5, 3.0, 3.5, 4.0])
- 使用
Quality作为变量col绘制非参数回归图:
g3 = sns.lmplot(x='fixed acidity', y='density',
data=wine_quality,lowess=True, markers='s',
col='Quality', col_order=['Low', 'Med', 'High'],
height=3, line_kws={'color': 'g'})
plt.show();
工作原理
这是代码的说明。
这是第一个绘图:
hue='Quality'将Quality指定为,hue变量,因此对于的每个唯一值,Quality变量将绘制具有不同颜色的回归图。hue_order=['Low', 'Med', 'High']是要绘制的色调变量值的顺序。logx=True指定拟合形式为y = log(x)的曲线。ci=None指定不围绕曲线绘制置信区间。
结果图如下所示:
这是第二个图:
ci=99指定绘制 99% 的置信区间。col='Quality'将Quality指定为列列变量,以便对于Quality的每个唯一值,它沿图的列绘制回归图。col_order=['Low', 'Med', 'High'指定图形在图形上的放置顺序。robust=True指定要减轻离群值对曲线拟合数据的影响。scatter_kws={'color': 'g'}指定以绿色绘制点。g2 = g2.set_axis_labels("Fixed Acidity", "pH")用用户定义的标签覆盖的默认轴标签。g2.set(xlim=(0, 20), ylim=(2.4, 4.0), xticks=[5, 10, 15, 20], yticks=[2.5, 3.0, 3.5, 4.0])会覆盖的默认轴限制和刻度。
结果图如下所示:
这是第三个绘图:
lowess=True指定拟合非参数回归模型markers='s'使用默认颜色绘制正方形的点line_kws={'color': 'g'}将拟合曲线绘制为绿色
生成的图看起来像这里显示的图:
多图网格
在本章前面的“具有长格式数据集的线形图和点图”秘籍中,当我们将row和col变量用于线形图中的各种可视化方面时,我们已经看到了某些类型的多图网格。 但是, seaborn 提供了三组用于不同用途的预定义网格。
jointplot()和JointGrid()启用,将创建三个轴域/图作为一个图形。 主轴域称为联合图,其他两个称为边缘轴域。 边缘轴域之一在联合图的顶部,第二边缘轴域在联合图的右侧。 在联合图上绘制了两个变量之间的关系,并且在每个边缘轴域上绘制了这两个变量中的每一个的单变量分布。 这些函数具有各种参数,可以灵活地在这三个轴域的每一个上选择和类型的图形。
pairplot()和PairGrid()可以成对出现,每个成对包含两个变量。 我们只需传递宽格式数据集,并使用一条语句,就可以得到以行和列的网格形式显示所有数值变量之间成对关系的图形。 同样,这里有许多选择不同类型图形的选项。
jointplot()和JointGrid()以及pairplot()和PairGrid()之间的区别在于,可以灵活地选择各种参数和每种参数提供的图形类型。jointplot()和pairplot()灵活性较差,但易于使用并可以快速绘制。JointGrid()和PairGrid()提供更多的灵活性,有许多参数可供选择。
FacetGrid()是多图网格的第三类。 用于hue,style,size,row和col变量的组合的多维分析。 我们已经在关系图和类别图的上下文中看到了这些。 他们在内部使用FacetGrid(); 在这里,我们将直接访问它。
jointplot()和JointGrid()
jointplot()使用kind参数启用了五种绘图。 我们将为五种图绘制五种具有不同参数的图。
我们将使用JointGrid()绘制另一组五个图,并利用其提供的灵活性来控制可在网格的三个轴域上绘制的图的类型和样式。
准备
这部分对于jointplot()和JointGrid()都是通用的,而“操作步骤”和“工作原理”部分将分别对它们分别重复。
导入所需的库:
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
from scipy.stats import norm
from itertools import chain # chain enables iteration of multiple lists
in loops such as for loop.
## The following parameters are set in rc configuration file, so they
will be applicable for the entire session
## font_scale factor is the multiplier of default font size(instead of
absolute size, it is relative size)
sns.set(rc={"axes.linewidth": 1, "xtick.major.width": 1,
"ytick.major.width": 1,
"xtick.major.size": 5, "ytick.major.size": 5},
style="ticks", context="paper", font_scale=1.25)
jointplot()
我们将为jointplot()支持的五种不同类型的绘图绘制五幅绘图。
操作步骤
以下是绘制和所需图形的步骤:
- 绘制回归图:
g1 = sns.jointplot(x='Pies', y='Smoothies', data=snacks_sales,
kind='reg',
marginal_kws=dict(bins=15, fit=norm, rug=True,
color='darkblue'),
space=0.1, color='g')
g1.ax_marg_x.set_title('1\. Regression Plot - Histogram, KDE, Normal,
Rug', size=20, color='g')
- 绘制散点图:
g2 = sns.jointplot(x='Cookies', y='Smoothies', data=snacks_sales,
s=100, marginal_kws=dict(kde=True, rug=True,
hist=False, color='orange'), space=0.1,
color='g', edgecolor="blue", alpha=0.6)
g2.ax_marg_x.set_title('2\. Scatter Plot - KDE, Rug', size=20,
color='g')
- 绘制 KDE 图:
g3 = sns.jointplot(x='Period', y='Smoothies', data=snacks_sales,
kind='kde', space=0, color='indigo')
g3.ax_marg_x.set_title('3\. KDE Plots', size=20, color='g');
- 绘制六角箱图:
g4 = sns.jointplot(x='Quarter', y='Pies', data=snacks_sales,
kind='hex', space=0, color='violet');
g4.ax_marg_x.set_title('4\. Hexbin Plot - Histograms', size=20,
color='g');
- 绘制残差图:
g5 = sns.jointplot(x='Cakes', y='Smoothies', data=snacks_sales,
kind='resid', space=0, color='c')
g5.ax_marg_x.set_title('5\. Residual Plot - Histogram, Normal',
size=20, color='g');
工作原理
这是代码的说明。
这是第一个绘图:
g = sns.jointplot()绘制了三个图的所需联合图。kind='reg'指定绘制回归图。marginal_kws=dict(bins=15, fit=norm, rug=True, color='darkblue')是要应用于,边缘轴域图的参数的字典。 它们适用于,上和右边缘轴域,但与联合绘图对象无关:bins=15是要绘制的直方图的仓数; 默认情况下,将绘制直方图。fit=norm指定为给定数据拟合normal分布曲线。rug=True绘制给定数据的地毯图。color='darkblue'是用于两个边缘轴域的所有元素的颜色。space=0.1指定,联合图和边缘轴域之间的间距。0表示它们紧密连接,彼此之间没有任何缝隙。color='g'指定联合绘图对象的颜色。- 默认情况下,KDE 曲线将适合数据。 如果我们不想绘制它,我们应该将其设置为
false。 在这种情况下,我们将同时具有 KDE 曲线和normal分布曲线。
g1.ax_marg_x.set_title('1\. Regression Plot - Histogram, KDE, Normal, Rug', size=20, color='g')绘制图的标题:ax_marg_x是顶部的边缘轴域。jointplot()内部调用JointGrid(),这使我们可以访问,联合图和两个边缘轴域。 我们将在接下来介绍的JointGrid()秘籍中详细了解它。size=20是标题的字体大小,color='g'将标题的颜色设置为绿色。
这是第二个图:
- 由于
kind='scatter'是默认设置,因此我们没有提供 kind 参数。 因此,它绘制了一个散点图。 s=100指定要绘制的每个点的大小。kde=True使 KDE 曲线适合给定数据。rug=True绘制地毯。hist=False不会绘制直方图。color='orange'是边缘轴域对象的颜色。space=0.1是,联合轴域和边缘轴域之间的间距。color='g'将绿色应用于联合绘图对象。edgecolor="blue"是,边缘,圆圈的颜色。alpha=0.6是和分散点的透明度。
执行后,这两个图应如下所示:
这是第三个图:
kind='kde'是二元 KDE 图space=0指定,联合轴域和边缘轴域之间没有空格color='indigo'是所有对象的颜色; 由于我们尚未提供marginal_kws,因此它对使用了相同的内容,边沿对象也是如此
这是我们的绘图:
kind='hex'表示六角箱图space=0表示联合轴域和边缘轴域之间没有间隙color='violet'是所有对象的颜色
执行代码后,第三和第四图应如下所示:
这是第五个绘图:
kind='resid'绘制残差绘图space=0表示,联合轴域和边缘轴域之间没有空间color='c'对所有对象使用青色颜色
执行前面的代码后,您应该看到第五张图,如下所示:
JointGrid()
我们将使用JointGrid()和各种参数绘制五幅图,以展示大多数可用功能。
操作步骤
以下是绘制和所需图的步骤:
- 使用默认参数和轴域级自定义创建一个简单的
JointGrid:
g1 = sns.JointGrid(x='Coffee', y='Cookies', data=snacks_sales,
space=0.1, height=6, ratio=2)
g1 = g1.plot(sns.regplot, sns.kdeplot)
##g = g.plot(plt.scatter, sns.distplot);
g1.ax_joint.set_xlabel('Coffee', color='g', size=20, weight='bold')
g1.ax_joint.set_ylabel('Cookies', color='g', size=20, weight='bold')
plt.setp(g1.ax_marg_x.get_yticklabels(), visible=True)
plt.setp(g1.ax_marg_x.get_xticklabels(), visible=True)
plt.setp(g1.ax_marg_y.get_xticklabels(), visible=True)
plt.setp(g1.ax_marg_y.get_yticklabels(), visible=True)
g1.ax_marg_x.set_facecolor('wheat')
g1.ax_marg_y.set_facecolor('wheat')
for l in chain(g1.ax_marg_x.axes.lines, g1.ax_marg_y.axes.lines):
l.set_linestyle('--')
l.set_lw(3)
l.set_color('red')
g1.ax_marg_x.set_title('1\. Regression Plot - KDE on marginals',
size=20, color='g')
- 用它们各自的参数分开联合和边缘图:
g2 = sns.JointGrid(x='Pies', y='Smoothies', data=snacks_sales,
space=0, ratio=2)
g2 = g2.plot_joint(sns.regplot, color="g", order=3, ci=68 )
g2 = g2.plot_marginals(sns.distplot, kde=False, rug=True, fit=norm,
color="#1EAFCD23")
g2.ax_marg_x.set_title('2\. Regression Plot - Histogram, Normal,
Rug', size=20, color='g')
- 将联合图,边缘
x和边缘y图分开,每个图上都有独立的控件:
g3 = sns.JointGrid(x='Pies', y='Smoothies', data=snacks_sales,
space=0, ratio=2)
g3 = g3.plot_joint(sns.regplot, color="g", order=3, ci=68)
g3.ax_marg_x.hist(snacks_sales['Pies'], color="b", alpha=.6,
bins=np.arange(0, 100, 5))
g3.ax_marg_y.boxplot(snacks_sales['Smoothies'], 1, 'gD')
g3.ax_marg_x.set_title('3\. Regression Plot - Histogram, Boxplot',
size=20, color='g');
- 在
JointGrid上实现hue:
g4 = sns.JointGrid("Cookies", "Smoothies", snacks_sales, space=0,
ratio=2)
i=1
for quarter, sales in snacks_sales.groupby('Quarter'):
sns.kdeplot(sales["Cookies"], ax=g4.ax_marg_x, label='Q'+str(i));
sns.kdeplot(sales["Smoothies"], ax=g4.ax_marg_y, vertical=True,
label='Q'+str(i));
g4.ax_joint.plot(sales["Cookies"], sales["Smoothies"], "D", ms=5)
i +=1
g4.ax_marg_x.set_title('4\. Scatter Plot - Histogram with hue, KDE on
marginals', size=20, color='g')
- 使用用户定义的联合和边缘图:
g5 = sns.JointGrid("Cookies", "Coffee", snacks_sales, space=0.5,
ratio=6)
def marginal_boxplot(a, vertical=False, **kws):
g = sns.boxplot(x="Promotion", y="Coffee", orient="v", **kws) if
vertical \
else sns.boxplot(x="Cookies", y="Promotion",
orient="h", **kws)
g.set_ylabel("")
g.set_xlabel("")
g5.plot_marginals(marginal_boxplot, palette={"Yes": "#ff000088", "No": "#00aa007e" }, data=snacks_sales,
linewidth=1, fliersize=10,notch=True)
sns.regplot(x="Cookies", y="Coffee", data=snacks_sales.query("Promotion == 'Yes'"), color="#ff000088",
truncate=True, label='Promotion: Yes', marker='D',
ax=g5.ax_joint,
scatter_kws={"s": 100, "edgecolor": "k", "linewidth":
.5, "alpha": .8})
sns.regplot(x="Cookies", y="Coffee", data=snacks_sales.query("Promotion == 'No'"),
color="#00aa007e", marker='^', label='Promotion: No',
scatter_kws={"s": 50, "edgecolor": "k", "linewidth": .5,
"alpha": .4},
line_kws={"linewidth": 2}, ax=g5.ax_joint)
g5.ax_marg_x.set_title('5\. Regression Plot with hue - Boxplots on
marginals', size=20, color='g')
g5.ax_joint.legend(loc=4)
plt.show();
工作原理
这是代码的说明:
这是第一个图:
g1 = sns.JointGrid()设置网格:space=0.1是联合图和边缘图之间的差距量。height=6是绘图的高度,以英寸为单位。ratio=2是联合绘图高度与边缘绘图高度的比率。
g1 = g.plot(sns.regplot, sns.kdeplot)指定联合图的图类型,和边缘图均指定。 也可以使用plt.scatter和sns.distplot等其他兼容图来代替sns.regplot和sns.kdeplot。g.plot()不能灵活地提供各种参数,它仅使用提供的绘图类型的的所有默认参数。 但是,可以进行轴域级自定义,如下所示:g1.ax_joint.set_xlabel('Coffee', color='g', size=20, weight='bold')会覆盖联合轴域的默认 x 轴标签。"ax_joint"是联合图的轴域名称。g1.ax_joint.set_ylabel('Cookies', color='g', size=20, weight='bold')或会覆盖联合轴域的默认 y 轴标签。- 使边缘轴域刻度标签可见:
plt.setp(g1.ax_marg_x.get_yticklabels(), visible=True)plt.setp(g1.ax_marg_x.get_xticklabels(), visible=True)plt.setp(g1.ax_marg_y.get_xticklabels(), visible=True)plt.setp(g1.ax_marg_y.get_yticklabels(), visible=True)ax_marg_x和ax_marg_y是的名称,上,右边缘轴域
g1.ax_marg_x.set_facecolor('wheat')设置,边缘 x 轴的面色(上图)。g1.ax_marg_y.set_facecolor('wheat')设置,边缘 y 轴的面色(右图)。for l in chain(g1.ax_marg_x.axes.lines, g1.ax_marg_y.axes.lines):是用于自定义两个边缘轴域上的折线图的循环:l.set_linestyle('--')是要使用的线条样式。l.set_lw(3)是线宽。l.set_color('red')是线条的颜色。
g1.ax_marg_x.set_title('1\. Regression Plot - KDE on marginals', size=20, color='g')绘制图形标题。ax_marg_x是顶部边缘轴域,并且标题被打印在其顶部。 这部分中的所有其他图都相同。
这是第二个图:
-
在这里,我们可以分别绘制,联合图和边缘图,并可以传递适当的属性以自定义它们。
-
如第一张图所示,
g2 = sns.JointGrid(x='Pies', y='Smoothies', data=snacks_sales, space=0, ratio=2)使用所需的数据设置了网格。 -
g2 = g2.plot_joint(sns.regplot, color="g", order=3, ci=68 )在联合轴域上绘制回归图:- 我们可以传递适用于
sns.regplot()的所有参数。 color="g"指定使用绿色。order=3,指定为所提供的数据拟合三阶多项式曲线。ci=68指定置信区间,将围绕拟合曲线绘制。
- 我们可以传递适用于
-
g2 = g2.plot_marginals(sns.distplot, kde=False, rug=True, fit=norm, color="#1EAFCD23")绘制两个边缘轴域上的分布图,提供的参数适用于以下两个方面:kde=False并未绘制 KDE 曲线。rug=True绘制地毯。fit=norm拟合法线。color="#1EAFCD23"使用十六进制形式指定的颜色。
执行前面的代码后,您应该在屏幕上看到以下两个图:
这是第三张图:
- 在这里,我们可以灵活地在两个边缘轴域上绘制不同类型的图。
g3 = sns.JointGrid()创建网格,如,的前两个图所示。g3 = g3.plot_joint(sns.regplot, color="g", order=3, ci=68)与第二个图中的相同。g3.ax_marg_x.hist(snacks_sales['Pies'], color="b", alpha=.6, bins=np.arange(0, 100, 5))在顶部边缘轴域上绘制直方图。- 从本质上讲,
g3.ax_marg_x就像标准的 matplotlib 轴域一样,我们可以使用 Matplotlib 图中的任何绘制任何东西。 在这里,我们正在绘制直方图,传递的参数来自 Matplotlib 直方图。 g3.ax_marg_y.boxplot(snacks_sales['Smoothies'], 1, 'gD')在,右边缘轴域上绘制箱形图。 同样,它是 Matplotlibboxplot和,传递的参数来自和 Matplotlibboxplot。1指定使用该槽口,默认为0的默认为没有槽口的矩形框。'gD'指定异常值的颜色和标记,在这种情况下为绿色和菱形。
这是第四张图:
- 在该图中,我们在
JointGrid上实现了hue,并且还在边缘轴域上绘制了 Seaborn 图。 在第三张图中,我们使用了 Matplotlib 图。 g4 = sns.JointGrid("Cookies", "Smoothies", snacks_sales, space=0, ratio=2)与所有JointGrid图的通常相同。i=1将索引初始化为 1。for quarter, sales in snacks_sales.groupby('Quarter'):是用于按季度对销售数据进行分组的for循环,因此它们可以在边缘轴域上绘制,而双变量数据可以在联合轴域上绘制:sns.kdeplot(sales["Cookies"], ax=g4.ax_marg_x, label='Q'+str(i))在顶部边缘轴域上使用标签 Q1,Q2,Q3 和 Q4 绘制 KDE 图,在for循环的每个迭代中使用一个。sns.kdeplot(sales["Smoothies"], ax=g4.ax_marg_y, vertical=True, label='Q'+str(i))在右边缘轴域上绘制另一个 KDE 图,其标签与顶部轴域相似:vertical=True指定以水平方向进行绘制。
g4.ax_joint.plot(sales["Cookies"], sales["Smoothies"], "D", ms=5)在和联合图上绘制散点图:"D"正在使用菱形标记ms=5是标记大小
执行上述代码后,您应该在屏幕上看到以下两个图:
这是第五个图:
- 在此,我们使用用户定义的函数在上绘制联合轴域和两个边缘轴域。 我们将继续产生色调效果。
g5 = sns.JointGrid("Cookies", "Coffee", snacks_sales, space=0.5, ratio=6)照常创建网格。def marginal_boxplot(a, vertical=False, **kws):是在边缘轴域域上绘制箱形图的函数:g5 = sns.boxplot(x="Promotion", y="Coffee", orient="v", **kws) if vertical\else sns.boxplot(x="Cookies", y="Promotion", orient="h", **kws)- 我们不是在调用此函数,而是将其传递给
sns.plot_marginals()函数,该函数会将vertical标志设置为True或False,取决于它要绘制的轴域,上一条语句检查此标志的状态,并适当映射数据和方向参数。 g5.set_ylabel("") and g5.set_xlabel("")从轴上删除默认标签。
g5.plot_marginals(marginal_boxplot, palette={"Yes": "#ff000088", "No": "#00aa007e" }, data=snacks_sales,linewidth=1, fliersize=10,notch=True)在边缘轴域上绘制箱形图:marginal_boxplot是我们定义的用于在边缘轴域上绘制箱形图的函数。palette为变量的不同值指定颜色代码,该变量被用作色相变量。linewidth=1指定在箱形图中绘制的线宽。fliersize=10指定超出胡须的异常值的大小。notch=True指定绘制带有缺口的框,而不是矩形框。
sns.regplot()对Promotion=Yes数据在联合轴域上绘制一次回归图,对Promotion=No进行第二次绘制。 所有参数均在回归图(lmplot()和regplot())中进行了详细讨论。 因此,我们在这里不再重复。g5.ax_joint.legend(loc=4)在联合轴域右下角的上绘制图例。
执行前面的代码块后,您应该在屏幕上看到第五个图,如下所示:
pairplot()和PairGrid()
pairplot()和PairGrid()允许在一个语句中将数据集中的所有数值变量成对绘制为两个。 这是了解整个数据集中变量之间存在的高级关系和联合的快速方法。 这加快了机器学习项目的特征设计过程。pairplot()对于双变量绘图只有两个选项:散点图和回归。PairGrid()没有任何这样的限制。
准备
此部分对于pairplot()和PairGrid()都是通用的,而“操作步骤”和“工作原理”部分将分别对它们分别重复。
导入所需的库:
import matplotlib.pyplot as plt
import seaborn as sns
## The following parameters are set in rc configuration file, so they
will be applicable for the entire session
## font_scale factor is the multiplier of default font size(instead of
absolute size, it is relative size)
sns.set(rc={"axes.linewidth": 1, "xtick.major.width": 1,
"ytick.major.width": 1,
"xtick.major.size": 5, "ytick.major.size": 5},
style="ticks", context="paper",
font_scale=1.25)
pairplot()
我们将数据集的仅作为数据集的子集,以免因变量太多而无法绘制出混乱的图表。 我们将仅包含五个项目, 促销变量,将用作色相变量。 以下代码提取所需的子集:
snacks_sales_items = snacks_sales.loc[:,['Cakes', 'Cookies', 'Pies',
'Smoothies','Coffee','Promotion']]
操作步骤
有三种方法可以指定要使用pairplot()绘制的网格类型。 让我们绘制所有三种格式并查看其中的区别:
- 在提供的数据集中绘制所有数字变量:
sns.pairplot(snacks_sales_items, hue='Promotion', kind='reg')
plt.show();
- 从提供的数据集中绘制所选变量:
sns.pairplot(snacks_sales, vars=['Coffee', 'Pies'], hue='Promotion',
kind='reg')
plt.show();
- 在行和列网格中绘制从提供的数据集中选择的变量,类似于我们先前使用的方面变量:
g = sns.pairplot(snacks_sales, x_vars=['Coffee', 'Pies', 'Cakes'],
y_vars=['Cookies', 'Smoothies'],
hue='Promotion', kind='scatter')
g.fig.subplots_adjust(wspace=.02, hspace=.02);
plt.show();
工作原理
这是前面代码的解释。
这是第一个绘图:
sns.pairplot(snacks_sales_items, hue='Promotion', kind='reg')创建并绘制所需的网格:snacks_sales_items是我们刚刚为此秘籍创建的数据集。hue='Promotion'指定色调变量。kind='reg'指定应为所有双变量图绘制回归图。- 在对角线上,默认情况下会绘制单变量
kdeplot()。
执行后,您应该在屏幕上看到以下图:
这是第二个图:
sns.pairplot(snacks_sales_items, vars=['Coffee', 'Pies'],hue='Promotion', kind='reg')仅绘制两个变量:Coffee和Pies。- 其他参数与第一个图相同。
执行后,您应该在屏幕上看到以下图:
这是第三个图:
g = sns.pairplot(snacks_sales_items, x_vars=['Coffee', 'Pies', 'Cakes'], y_vars=['Cookies', 'Smoothies', hue='Promotion', kind='scatter')将创建一个3 x 2的网格,并在行中绘制x_vars,在列中绘制y_vars。kind='scatter',绘制双变量散点图。g.fig.subplots_adjust(wspace=.02, hspace=.02),可以水平和垂直调整绘图之间的间隔。 这也可以应用于第一图和第二图。
执行代码后,您应该在屏幕上看到以下图表:
PairGrid()
PairGrid()与pairplot()的工作原理非常相似,但提供了更大的灵活性,可以将任何类型的图分别用于对角线,非对角线甚至更低和更高的对角线图。 但是,PairGrid()不支持pairplot()的行和列矩阵网格,因为它沿对角线使用单变量图,而行和列网格仅具有双变量绘图。
操作步骤
除了完整的数据集和选定的变量列表之外,它还有三种方法可以在网格中指定图的特定类型:
- 对网格中的所有图形单元/轴域使用相同类型的图:
g = sns.PairGrid(snacks_sales_items, hue='Promotion', hue_kws=
{"marker": ["^", "D"]},
palette={'Yes': 'blue', 'No': '#00a99f05'})
g.map(plt.scatter, edgecolor='k', s=50)
g.add_legend()
g.fig.subplots_adjust(wspace=.02, hspace=.02);
- 将一种类型的单变量图用于对角线,将另一种双变量类型用于非对角线图:
g = sns.PairGrid(snacks_sales_items, vars=['Coffee', 'Pies',
'Smoothies'], hue='Promotion', palette={'Yes':
'Orange', 'No': 'g'})
g.map_diag(plt.hist, histtype="step", linewidth=2)
g.map_offdiag(sns.kdeplot, n_levels=25, cmap="coolwarm")
g.add_legend()
g.fig.subplots_adjust(wspace=.02, hspace=.02);
- 对于对角线使用一种单变量,对于对角线使用一种双变量类型,对于下部对角线图使用另一种双变量类型:
g = sns.PairGrid(snacks_sales_items, vars=['Cakes', 'Pies',
'Cookies'], hue='Promotion',
palette={'Yes': 'darkblue', 'No': 'r'})
g.map_diag(sns.stripplot, jitter=True)
g.map_upper(sns.regplot, order=2, ci=90)
g.map_lower(sns.residplot, order=2, lowess=True)
g.add_legend();
工作原理
这是前面代码的解释:
这是第一个绘图:
g = sns.PairGrid(snacks_sales_items, hue='Promotion', hue_kws={"marker": ["^", "D"]},palette={'Yes': 'blue', 'No': '#00a99f05'})为数据集中的所有变量创建网格:hue_kws={"marker": ["^", "D"]}指定要用于hue变量Promotion的Yes和No值的标记palette={'Yes': 'blue', 'No': '#00a99f05'}指定颜色代码,它是用于色调变量的唯一值
g.map(plt.scatter, edgecolor='k', s=50)在网格上的每个图上绘制散点图:edgecolor='k'将散点图的上的点的边缘指定为黑色。s=50指定散点图上点/标记的大小。
g.add_legend()将图例添加到图形的中。 由于某些原因,seaborn不会像所有其他类型的绘图一样自动添加!g.fig.subplots_adjust(wspace=.02, hspace=.02),可水平和垂直调整绘图之间的间隔。
执行代码后,您应该在屏幕上看到以下图:
这是第二个绘图:
-
g = sns.PairGrid()与以前一样创建网格,并使用和标准参数 -
g.map_diag(plt.hist, histtype="step", linewidth=2)指定在所有对角线上绘制直方图:histtype="step"是一个楼梯,而不是平滑的曲线。linewidth=2是直方图的线的宽度。
-
g.map_offdiag(sns.kdeplot, n_levels=25, cmap="coolwarm")在所有非对角线上绘制 kde 图:n_levels=25指定要绘制的轮廓数量。cmap='coolwarm'是用于绘制轮廓的颜色表。g.add_legend()添加图例。g.fig.subplots_adjust(wspace=.02, hspace=.02)调整绘图之间的间隔。
执行代码后,您应该在屏幕上看到以下图:
这是第三个绘图:
g = sns.PairGrid()为数据集中的一组选定变量创建网格。g.map_diag(sns.stripplot, jitter=True)在对角单元上绘制条形图,并设置了抖动,以使所有点都不落在一条直线上。g.map_upper(sns.regplot, order=2, ci=90)回归图绘制在和上对角线单元中:order=2指定将二阶多项式拟合到给定数据。ci=90围绕拟合多项式绘制 90% 的置信区间。
执行代码后,您应该在屏幕上看到以下图:
FacetGrid()
如前所述,FacetGrid()用于执行,语义变量hue,style和size以及方面变量row和col进行多维分析。 当我们了解关系图和类别图时,我们已经间接使用了这些功能。
准备
导入所需的库:
import matplotlib.pyplot as plt
import seaborn as sns
## The following parameters are set in rc configuration file, so they
will be applicable for the entire session
## font_scale factor is the multiplier of default font size(instead of
absolute size, it is relative size)
sns.set(rc={"axes.linewidth": 1, "xtick.major.width": 1,
"ytick.major.width": 1,
"xtick.major.size": 5, "ytick.major.size": 5},
style="ticks", context="paper",
font_scale=1.25)
操作步骤
以下是绘制各种FacetGrid()图以演示其功能的步骤:
- 绘制单变量直方图:
g = sns.FacetGrid(snacks_sales, col="Promotion", row="weekend",
height=3)
g = g.map(plt.hist, "Cookies", bins=10, color='m')
- 绘制双变量群图:
g = sns.FacetGrid(snacks_sales, col="Promotion", row="weekend",
height=3, margin_titles=True)
g = g.map(sns.swarmplot, "Quarter","Smoothies", order=[1, 2, 3, 4],
color='g')
- 绘制一个二元回归图:
g = sns.FacetGrid(snacks_sales, col="Quarter", row="weekend",
hue="Promotion",hue_order=['Yes', 'No'],
height=3, margin_titles=True, palette="Set2",
hue_kws=dict(marker=["^", "v"]))
g = g.map(sns.regplot, "Cookies","Coffee")
g.set(xlim=(200, 900), ylim=(100,800))
g.add_legend();
- 绘制双变量点图:
day_order = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
'Saturday', 'Sunday']
item_order = ['Coffee', 'Cakes', 'Pies', 'Cookies', 'Smoothies']
g = sns.FacetGrid(long_sales, col="daywk",col_wrap=3,
col_order=day_order, hue="Promotion",
hue_order=['Yes', 'No'], palette="Set1", height=3,
legend_out=False,
aspect=1.5, margin_titles=True)
g = g.map(sns.pointplot, "Item","Sales",
order=item_order).set_titles("{col_name}").add_legend()
g = g.fig.subplots_adjust(wspace=.05, hspace=.15);
工作原理
这是前面代码的解释:
这是第一个绘图:
g = sns.FacetGrid(snacks_sales, col="Promotion", row="weekend", height=3)创建网格:snacks_sales是输入数据帧。col="Promotion"指定Promotion作为列变量。row="weekend"将weekend指定为行变量。height=3指定网格中每个图的高度。- 默认长宽比为 1,这意味着宽度与高度相同。
g = g.map(plt.hist, "Cookies", bins=10, color='m')在网格的所有图上绘制直方图:bins=10,指定直方图中桶的个数。color='m',指定使用洋红色作为颜色。
这是第二个图:
g = sns.FacetGrid(snacks_sales, col="Promotion", row="weekend", height=3, margin_titles=True)创建网格:margin_titles=True指定的标题,行变量绘制在最后一列的右侧。
g = g.map(sns.swarmplot, "Quarter","Smoothies", order=[1, 2, 3, 4], color='g')绘制了Smoothies季度销售量的群体图。order=[1, 2, 3, 4]指定要在 x 轴域上绘制四分之一的顺序; 由于它是一个数字值,因此可以自动采用升序。color='g'将绘图上的点涂成绿色。
执行这两个图的代码后,您应该在屏幕上看到以下图:
这是第三个图:
-
g = sns.FacetGrid()创建所需的网格:col="Quarter"将Quarter映射到列变量。row="weekend"将weekend映射到行变量。hue="Promotion"将Promotion映射到色调变量。hue_order=['Yes', 'No']是绘制它们的顺序。height=3将每个绘图的高度设置为 3 英寸。margin_titles=True设置行变量的标题,以绘制在最后一列的右侧。palette="Set2"使用预定义的调色板。hue_kws=dict(marker=["^", "v"])指定将这些标记用于Promotion变量的的唯一值。
-
g = g.map(sns.regplot, "Cookies","Coffee")绘制了Cookies和Coffee变量的回归图 -
g.set(xlim=(200, 900), ylim=(100,800)),设置 x 和 y 轴限制 -
g.add_legend()表示,由于现在添加了和色相变量,因此我们可以绘制图例。
执行上述代码后,您应该在屏幕上看到以下图:
这是我们的绘图:
day_order是指定工作日绘制顺序的列表item_order是指定绘制项目顺序的列表g = sns.FacetGrid()使用和以下属性创建网格:long_sales是的长格式数据帧,其中包含要绘制的数据。col="daywk"将变量daywk映射到列。col_wrap=3,指定将每三列后的后续图包装成行。col_order=day_order,指定要绘制星期几的顺序。hue="Promotion"是映射到hue的Promotion变量。hue_order=['Yes', 'No']是绘制Promotion值的顺序。palette="Set1"是要使用的调色板。height=3是每个图的高度。aspect=1.5是网格中每个图的宽度,应为1.5乘以高度。legend_out=False指定不将图例推到右侧的图外。 然后,选择作为要打印的绘图中的最佳位置。 默认设置是在中心右侧的绘图区域外进行绘图。margin_titles=True表示行变量的标题绘制在最后一列的右侧。
g = g.map(sns.pointplot, "Item","Sales", order=item_order).set_titles("{col_name}").add_legend():- 绘制项目和销量的点图。
order=item_order按此顺序绘制item。set_titles("{col_name}")使用相应绘图的col_name设置标题,而不使用默认标题。add_legend()将图例添加到图形中。
g = g.fig.subplots_adjust(wspace=.05, hspace=.15),调整绘图之间的间隔。
执行上述代码后,您应该在屏幕上看到以下图:
矩阵图
尽管pairplot()和PariGrid()可以绘制每个变量包含两个变量的网格中的多个变量之间的关系,但矩阵图可以通过使用与变量相关的聚合度量(例如相关性,协方差)以矩阵格式启用此格式,或者可以正常使用两个相关变量的财务,销售或运营等数据。
Seaborn 提供了两个矩阵图,heatmap()和clustermap()。
Heatmap()提供数字的彩色表示,以了解数字的增加,减少,偏离或收敛的趋势,这可能不容易直接用数字捕捉,特别是当数字太小或太大时。
Clustermap()使用分层聚类方法,并绘制和生成的树状图。
热图
热图通过使用色表表示颜色中的数字,因此我们的眼睛可以捕捉到和数据中各种变量的相对强度。
准备
导入和所需的库。 设置背景样式并准备绘制图形所需的数据。
我们将使用和相同的长格式数据帧作为输入,按Item和Quarter分组以按季度获得各种商品的销售额,并根据其中的数据表创建一个数据透视表,仍是数据帧格式,可以将其提供给 Seaborn 绘图:
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(style='white')
## Prepare the data in matrix format with Quartes on rows and Items in
columns
sales = pd.DataFrame(long_sales.groupby(["Item",
"Quarter"]).Sales.mean())
sales = sales.reset_index()
sales = sales.pivot('Quarter','Item', 'Sales')
sales.head()
操作步骤
这是绘制和所需图形的步骤。 我们将绘制三个数字,一个接一个。 第一个图将具有三个图,第二个图将有一个图,第三个图将有两个图:
- 定义第一个图形对象并定义轴域对象,我们将在其上绘制 Seaborn 图:
fig, (ax1, ax2, ax3) = plt.subplots(1,3, figsize=(15,5))
2.用预定义的颜色表绘制热图:
sns.heatmap(sales, annot=True, fmt='.0f', linewidths=.5,
cmap="YlGnBu", ax=ax1)
ax1.set_title('Using pre-defined Colorbar')
- 绘制热图,带有以特定值为中心的色表:
sns.heatmap(sales, annot=True, fmt='.0f',linewidths=.5, robust=True,
cmap="YlGnBu", center=sales.loc[3, 'Cookies'],
yticklabels=False, ax=ax2)
ax2.set_title("Colorbar Centered at [3, 'Cookies']")
- 绘制设置了颜色表显示的热图:
sns.heatmap(sales, annot=True, fmt='.0f',linewidths=.5, robust=True,
vmin=200, vmax=600,
cmap="YlGnBu", yticklabels=False, ax=ax3)
ax3.set(title='Colorbar range(200, 600)', ylabel='')
- 调整绘图之间的间距,并在屏幕上显示图形:
plt.tight_layout()
plt.show();
- 在第二个图形对象上定义,并在单独的轴域上绘制热图和色条,并使用水平色条:
grid_kws = {"height_ratios": (.9, .05), "hspace": .4}
f, (plot_ax, cbar_ax) = plt.subplots(2, gridspec_kw=grid_kws)
ax = sns.heatmap(sales, ax=plot_ax, cmap="Set1", annot=True,
fmt='.0f',linewidths=.5,
cbar_ax=cbar_ax, cbar_kws={"orientation":
"horizontal"});
- 定义第三个图,并绘制
wine_quality相关矩阵的热图:
fig, (ax1, ax2) = plt.subplots(1,2, figsize=(16,6))
sns.heatmap(corr, annot=True, fmt='.2f',linewidths=.5,
cmap="inferno", ax=ax1)
- 在上一步中定义的第三个图上绘制部分相关矩阵的热图:
mask = np.zeros_like(corr)
mask[np.triu_indices_from(mask)] = True
sns.heatmap(corr, mask=mask, vmax=.3, annot=True, fmt='.2f',
cmap="inferno", ax=ax2)
- 在屏幕上显示该图:
plt.show();
工作原理
这是前面代码的解释。
这是第一个数字:
-
fig, (ax1, ax2, ax3) = plt.subplots(1,3, figsize=(15,5))连续定义图形和三个轴域。 -
sns.heatmap(sales, annot=True, fmt='.0f',linewidths=.5, cmap="YlGnBu", ax=ax1)绘制热图:sales是季度和项目销售数据帧。annot=True指定在图上显示实际数字。fmt='.0f'指定和数字应以整数格式显示,没有任何十进制值。linewidths=0.5指定应使用此宽度的线来绘制所有行和列。cmap=" YlGnBu"指定预定义的颜色表。ax=ax1指定要在其上绘制该图的轴域。
-
ax1.set_title('Using pre-defined Colorbar')绘制第一个图的标题。 -
sns.heatmap(sales, annot=True, fmt='.0f',linewidths=.5, robust=True, cmap="YlGnBu", center=sales.loc[3, 'Cookies'], yticklabels=False, ax=ax2)绘制了和第二个热图,该色表的中心位于和指定值处:robust=True:当未指定vmin和vmax范围时,色表范围是通过降低异常值的权重得出的。center=sales.loc[3, 'Cookies']将此颜色表的中心颜色设置为该值,并将颜色条调整为要绘制的数据范围。 如果选择的值在数据范围的任意一个极端上,则仅将原始色表的一半用于新色条。yticklabels=False关闭此图的 Y 轴的刻度标签。ax=ax2是绘制此图的轴域。
-
sns.heatmap(sales, annot=True, fmt='.0f',linewidths=.5, robust=True, vmin=200, vmax=600, cmap="YlGnBu", yticklabels=False, ax=ax3)绘制了另一个热图,并在色条上设置了限制:vmin=200是的下限,vmax=600是上限。 数据中低于下限的所有数字,都以颜色条的下端着色,高于上限的数字都以颜色条的上端着色。
-
ax3.set(title='Colorbar range(200, 600)', ylabel='')打印标题并关闭 y 轴标签。 -
plt.tight_layout()调整绘图之间的间隔,以确保没有重叠。
执行上述代码后,您应该在屏幕上看到以下图:
这是第二个数字:
f, (plot_ax, cbar_ax) = plt.subplots(2, gridspec_kw=grid_kws)定义图形和一列中的两个轴域。grid_kws = {"height_ratios": (.9, .05), "hspace": .4}是网格的参数字典。 和两个轴域的高度之比为0.9:0.05,因此和色条轴域的高度与绘图高度相比非常短。 两个轴域之间的水平间距为 0.4。ax = sns.heatmap(sales, ax=plot_ax, cmap="Set1", annot=True, fmt='.0f',linewidths=.5, cbar_ax=cbar_ax, cbar_kws={"orientation": "horizontal"})绘制热图:sales是要绘制的数据。ax=plot_ax指定要放置绘图的轴域。cmap= "Set1"是另一个预定义的颜色表。annot=True在绘图上显示数字。fmt='.0f'数字显示时不带十进制值。linewidths=0.5线以 0.5 的宽度绘制在矩阵中。cbar_ax=cbar_ax指定颜色条轴域。cbar_kws={"orientation": "horizontal"})绘制水平颜色条。
执行上述代码后,您应该在屏幕上看到以下图:
这是第三个数字:
fig, (ax1, ax2) = plt.subplots(1,2, figsize=(16,6))定义第三个图形,带有一行中的两个轴域。sns.heatmap(corr, annot=True, fmt='.2f',linewidths=.5, cmap="inferno", ax=ax1)绘制,相关矩阵,和wine_quality数据的热图。 最后两个图中已经说明了所有参数。- 对于第二个绘图,
mask = np.zeros_like(corr)使用corr矩阵的相同大小创建遮罩,并用零填充。 mask[np.triu_indices_from(mask)] = True将上对角线的所有元素设置为True,其他元素(对角线和下对角线单元)将保留为False(0)。sns.heatmap(corr, mask=mask, vmax=.3, annot=True, fmt='.2f', cmap="inferno", ax=ax2)绘制热图:mask=mask指定要应用于整个矩阵的遮罩。 它仅显示设置为Zero(False)的条目,并隐藏设置为True(1).的条目。它将mask矩阵中的索引与corr矩阵匹配。vmax = 0.3,将颜色条的限制设置为 0.3。 所有高于 0.3 的值将用颜色条顶部的颜色进行着色。cmap="inferno"设置要在此处使用的另一个预定义颜色表。
执行上述代码后,您应该在屏幕上看到以下图:
群集图
顾名思义,clustermap()使用分层聚类方法对数据集中的各种变量进行聚类,并绘制和生成的树状图。
准备
导入所需的库:
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
sns.set(style='white')
操作步骤
以下是绘制两个聚类图的步骤,一个在Wine Quality数据集中具有原始数据,另外一个在相关的相关矩阵中:
- 绘制
Wine Quality数据集的聚类图:
row_colors =
wine_quality["Quality"].map(dict(zip(wine_quality["Quality"].unique
(), "rbg")))
g = sns.clustermap(wine_quality.drop('Quality',axis=1),
standard_scale=1, robust=True,
row_colors=row_colors, cmap='viridis')
- 绘制
Wine Quality数据集的相关矩阵的聚类图:
g = sns.clustermap(corr, figsize=(10,8), z_score=1, cbar_kws={"label":
"color bar"})
工作原理
这是代码的说明:
Wine Quality数据集中的Quality变量具有Low,Med和High值,分别具有63,1319和217计数。 我们要突出显示群集中的哪些观测值属于哪个质量等级。 因此,我们提取这三个唯一值,并为其分配红色,绿色和蓝色三种颜色,以便和对应的观察结果相应地着色:
row_colors = wine_quality["Quality"].map(dict(zip(wine_quality["Quality"].unique(), "rbg")))获取所有观测值的索引,并为分配适当的颜色代码,分别对应Low(绿色),Med(蓝色)和High(红色)值。g = sns.clustermap(wine_quality.drop('Quality',axis=1), standard_scale=1, robust=True, row_colors=row_colors, cmap='viridis')绘制群集图:wine_quality.drop('Quality',axis=1)从群集映射中删除了Quality变量,因为它已用作色调。standard_scale=1,指定标准化数据集中的所有变量。 这可以按行或按列进行。 我们要按列进行操作,因为我们想标准化按列组织的变量。 本质上,它计算变量的最小值和最大值,然后从每个值中减去最小值,然后将结果除以最大值。 这有助于改善模型的表现。row_colors=row_colors指定要在聚类地图上显示的观测值的颜色代码。cmap='viridis'指定要使用的颜色表。- 我们可以尝试使用,
method参数分配链接的不同方法,以及使用metric参数分配距离的指标。 有关更多详细信息,请参考这里。 - 我们可以分别使用
g.dendrogram_row.reordered_ind和g.dendrogram_col.reordered_ind来获取,行和群集的col索引的序列,其中g是clustermap对象。
执行上述代码后,您应该在屏幕上看到以下图:
进一步的解释如下:
g = sns.clustermap(corr, figsize=(10,8), z_score=1, cbar_kws={"label": "color bar"})绘制了Wine Quality数据集的相关矩阵的聚类图:figsize=(10,8)指定要在其中绘制群集图的图形的大小。z_score=1是另一种标准化方法,其中为每个变量计算均值和标准差,从每个元素中减去均值,然后将其除以标准差,以便结果变量分布的平均值为零,标准差/方差为 1。
执行上述代码后,您应该在屏幕上看到以下图: