900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > [学习笔记]Python for Data Analysis 3E-9.绘图和可视化

[学习笔记]Python for Data Analysis 3E-9.绘图和可视化

时间:2020-04-07 09:30:43

相关推荐

[学习笔记]Python for Data Analysis  3E-9.绘图和可视化

进行信息可视化(有时称为绘图)是数据分析中最重要的任务之一。它可能是探索过程中的一部分-例如,帮助识别异常值或所需的数据转换,或作为生成模型想法的一种方式。对于其他人来说,为Web构建交互式可视化可能是最终目的。Python有许多用于制作静态或动态可视化的附加库,但我们主要关注matplotlib和构建在其上的库。

matplotlib是一个桌面绘图包,旨在创建适合出版的绘图和图形。该项目由约翰·亨特于2002年启动,目的是在Python中启用类似MATLAB的绘图界面。matplotlib和IPython社区合作简化了IPython shell(也就是现在的Jupyter notebook)的交互式绘图。matplotlib支持所有操作系统上的各种GUI后端,并且可以将可视化导出为所有常见的矢量和光栅图片格式(PDF、SVG、JPG、PNG、BMP、GIF等)。除了一些图表外,本书中几乎所有图形都是使用matplotlib制作的。

随着时间的推移,matplotlib已经催生了许多用于数据可视化的附加工具包,这些工具包使用matplotlib进行底层绘图。其中之一就是seaborn,我们将在本章后面讨论。

按照本章的代码示例操作的最简单方是在Jupyter笔记本中输出绘图。在开始之前,需要在Jupyter notebook中执行以下语句:

%matplotlib inline

注意:自本书第一版出版以来,已经创建了许多新的数据可视化库,其中的一些(如Bokeh和Altair)利用现代Web技术创建了与Jupyter notebook集成很好的交互式可视化。我没有在本书中使用多种可视化工具,而是坚持使用matplotlib来教授基础知识,特别是因为pandas与matplotlib具有良好的集成度。你可以适应本章的原理来学习如何使用其他可视化库。

9.1一个简短的matplotlib API入门

对于矩阵,我们使用以下导入约定:

import matplotlib.pyplot as plt

在Jupyter中运行%matplotlib notebook(或在IPython中简单地运行%matplotlib)后,我们可以尝试创建一个简单的绘图。如果一切设置正确,则会出现如图9.1的线图

%matplotlib notebook # 不运行这个命令则不会有上面和下面的功能框data = np.arange(10)plt.plot(data)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dvg83u06-1669683258059)(/static/jkWQE6RtuJT9WMBeRFrWJE/image.png?auth_key=1669683251-eBbjdGqnVMeZ4XmiPdivov-0-652507c5eaeb2a931eb825823dd7eec8)]

虽然像seaborn和pandas的内置绘图函数将处理制作绘图的许多平凡细节,但如果你希望在提供的函数选项之外自定义它们,则需要学习一些matplotlib API的知识。

注意:书中没有足够的空间来给出matplotlib中功能的广度和深度的全面知识。但也足够教你起步。matplotlib库和文档是学习高级功能的最佳资源。

图形和子图

matplotlib中的绘图位于Figure对象中。你可以使用plt.figure 命令创建新figure:

# 在IPython中,如果你首先运行%matplotlib来启动matplotlib集成,则会出现一个空的绘图窗口。# 在Jupyter中,如果你首先运行%matplotlib notebook来启动matplotlib集成,则也会出现一个空的绘图窗口。%matplotlib notebook # 没有%matplotlib notebook则没有绘图窗口fig = plt.figure() # 创建新的绘图窗口# plt.figure有许多参数;值得注意的是,图片被存储到磁盘时,figsize会保证图形具有一定的大小和纵横比。# 你不能用空白figure绘图。你必须使用add_subplot函数创造一个或多个子图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ieh9UrNJ-1669683258060)(/static/x7MTw2TY3sNXNZyWVY99w1/image.png?auth_key=1669683251-6autBr7aRYMVgtDKRpMxUD-0-adce66fadcd6ade03bb54c6b3a2b2040)]

ax1 = fig.add_subplot(2, 2, 1) # 前两个参数意味着最多有2*2=4个图,1表示在绘图窗口上创建第1个子图(编号从1开始)# 创建编号为2和3的子图,最终会得到如图9.2的效果ax2 = fig.add_subplot(2, 2, 2)ax3 = fig.add_subplot(2, 2, 3)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DOf6Rfqv-1669683258060)(/static/quPrB66jo7cMBmck1gf8c1/image.png?auth_key=1669683251-qZXSheRvrRJnPtkKHgBuYf-0-b0cd71ac79e6c0bfbab965afafdaa50d)]

提示:使用Jupyter notebook的一个细微差别是,在计算每个cell后会重置绘图,所以你必须把所有绘图命令放在单个cell中

fig = plt.figure()ax1 = fig.add_subplot(2, 2, 1)ax2 = fig.add_subplot(2, 2, 2)ax3 = fig.add_subplot(2, 2, 3)

这些plot axes对象具有多种方法创建不同类型plots,如plt.plot。例如,我们可以用plot方法绘制如图9.3的线图

# 要在上面的ax3的对象上绘图,则%matplotlib notebook生成的绘图窗口不能关闭ax3.plot(np.random.standard_normal(50).cumsum(), color='black', linestyle='dashed') # 绘图并返回:[<matplotlib.lines.Line2D at 0x1220f99d0>]# 你可能会注意到,运行此命令的输出,如<matplotlib.lines.Line2D at ...>。matplotlib会返回刚刚添加的绘图子组件对象的引用。很多时候,你可以安全地忽略这个输出# 你也可以在行尾放置一个分号来抑制输出# 附加选项指示matplotlib绘制一条黑色虚线。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IXgXGvZ4-1669683258060)(/static/aaPEgfWAPunXdJvutHp8st/image.png?auth_key=1669683251-iL2X1RG99TbHxt5gg2Nm3z-0-012cb1ebe0243ea5182898bf4164b2ff)]

# fig.add_subplot函数返回的对象是AxesSubplot对象,你可以通过调用示例的方法直接在其他空图上绘制如图9.4的图ax1.hist(np.random.standard_normal(100), bins=20, color='black', alpha=0.3); # 根据100个正太样本绘制20个直方图,alpha为透明度ax2.scatter(np.arange(30), np.arange(30) + 3 * np.random.standard_normal(30)); # 根据样本绘制二维散点图plt.close('all') # 关闭所有绘图窗口

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xdkEROUR-1669683258061)(/static/fEDD1Dwc1GmsriaJeDqxeH/image.png?auth_key=1669683251-6mwJTRAX9P2QPMJvLUA3hg-0-d47149cb837887fba035d80b2a49757b)]

为了使创建子图网络更加方便,matplotlib包含了一个plt.subplots方法,该方法创建一个新figure并返回一个包含所创建子绘图对象的NumPy数组

fig, axes = plt.subplot(2, 3) # 创建下面的绘图窗口# 并返回数组:array([[<AxesSubplot:>, <AxesSubplot:>, <AxesSubplot:>], [<AxesSubplot:>, <AxesSubplot:>, <AxesSubplot:>]], dtype=object)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4Inq3mIS-1669683258061)(/static/jYSRCcaUwrqYAYHrhi5fLM/image.png?auth_key=1669683251-rHMNwRQRtkJn38HBWuo5sK-0-998ee12a6edbefa5cd023af769d444dd)]

# axes数组可以像二维数组一样进行索引,axes[0, 1]是指最上面中间的子图。# 你还可以使用sharex和sharey参数来指示子图应该具有相同的x轴和y轴。这在你比较相同尺度的数据时很有用;否则,matplotlib会自动缩放绘图比例。

下表是有关subplots方法的更多信息。

[表]matplotlib.pyplot.subplots参数

调整子图周围的间距

默认情况下,matplotlib会在子图的外部和子图之间的间距上留下一定量的填充。此间距是与plot的高度和宽度相关的,所以,如果以编程方式或使用GUI窗口手动调整plot大小,plot会自动调整自身。

# 你可以使用在Figure对象上使用subplots_adjust方法更改间距:subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)# wspace和hspace分别控制figure宽度和figure高度的百分比,以用作子图之间的间距。# 下面是一个可在Jupyter中执行的小示例,我们将间距缩小到0fig, axes = plt.subplots(2, 2, sharex=true, sharey=True) # 创建2乘2的子图窗口for i in range(2):for j in range(2):axes[i, j].hist(np.random.standard_normal(500), bins=50, color='black', alpha=0.5) # 在四个子图上根据500个正太样本绘制直方图fig.subplots_adjust(wspace=0, hspace=0)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QIY9Q9rT-1669683258062)(/static/eQPN2h422rNr57dd6PMQDE/image.png?auth_key=1669683251-mSu5whEDhPdwmR6oWMc5yD-0-85a5f00f5b720f6a1a936e6e4382e998)]

你可能会注意到轴标签重叠。matplotlib不会检查标签是否重叠。所以在这种情况下,你需要通过指定显式刻度位置和刻度标签来自行修复标签(我们将在后面的’刻度、标签和图例’部分中介绍如何执行此操作)。

颜色、标记和线条样式

matplotlib的线plot函数接受x和y坐标数组以及可选的颜色样式选项。

# 例如,要绘制带绿色虚线的折线图,你可以执行ax.plot(x, y, linestyle='--', color='green')

对于常见颜色,许多颜色名称被提供,但你可以通过指定十六进制编码(如’#CECECE’来使用光谱上的任何颜色。你可以通过查看plt.plot的文档字符串(在Ipython或Jupyter中使用plt.plot?)来查看一些支持的线条样式。在线文档中提供了更全面的参考。

线图还可以额外有标记用于突出显示实际数据点。由于matplotlib的plot函数创建连续的线图,在点之间插值,因此偶尔会看不清点的位置。标记可以作为附加样式选项提供(见图9.6):

fig = plt.figure()ax = fig.add_subplot()ax.plot(np.random.standard_normal(30).cumsum(), color='black', linestyle='dashed', marker='o');plt.colse('all')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xel9lMJl-1669683258062)(/static/rM7czP2sNkRzJayt48VrdJ/image.png?auth_key=1669683251-3Dp7jzAMsm1QQV6nwdhAQa-0-006c39cf25b37eef26d99afd2dbe788f)]

对于线图,可以注意到后续点在默认情况下是线性插值。这可以通过drawstyle参数更改(见图9.7):

fig = plt.figure()ax = fig.add_subplot()data = np.random.standard_normal(30).cumsum()ax.plot(data, color='black', linestyle='dashed', label='Default');ax.plot(data, color='red', linestyle='dashed', drawstyle='steps-post', label='steps-post'); # ax.legend() # 标注图例

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mzBK9cTU-1669683258063)(/static/aLi46ubfM1tZMSRME5kQsP/image.png?auth_key=1669683251-sYaWpmeoHGEWF9GRafWD7q-0-ce5ad9f993417d04eb59a6349715b4f0)]

在这里,由于我们将label参数传递给plot,我们可以通过ax.legend来创建图例来识别每条线。在’刻度、标签和图例’会更多地讨论图例。

注意:必须调用ax.legend才能创建图例,但是必须有label参数的线才会显示在图例上

刻度、标签和图例

大多数类型的绘图装饰可以通过matplotlib axes对象上的方法进行访问。这包括方法如xlim,xticks和xticklabels。这些方法可以控制plot的范围,刻度位置和刻度标签。它们可以以两种方式被使用:

查看当前参数的值(如ax.get_xlim()会返回当前x轴绘图范围)设置参数值(如ax.set_xlim(0, 10)会将x轴范围设置为0到10)

所有这些方法都做用于激活的或者最近创建的AxesSubplot对象。

设置标题、轴标签、刻度线和刻度标签

为了说明自定义轴,我将创建一个简单的图形和随机游走的绘图(参见图9.8)

fig, ax = plt.subplots()ax.plot(np.random.standard_normal(1000).cumsum());

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2zVlQAW1-1669683258063)(/static/74pBJTUCvYWERBpioSXQrA/image.png?auth_key=1669683251-niigSwZFWC3rSiYtj9gx3e-0-b079765a39a8a1298c8f36c2850ce7a6)]

# 调用set_xticks方法更改x轴刻度,并默认将值设置为轴标签ticks = ax.set_xticsk([0, 250, 500, 750, 1000]) # 将x轴刻度变更为[0, 250, 500, 750, 1000],其中0,250,500,750,1000是标签# 调用set_xticklabels方法更改x轴刻度标签labels = ax.set_xticklabels(['one', 'two', 'three', 'four', 'five'], rotation=30, fontsize=6)# 将['one', 'two', 'three', 'four', 'five']设置为标签# rotation选项使得x轴刻度标签逆时针旋转30度,fontsize设定了字体大小为6# set_xlabel方法为x轴重命名ax.set_xlabel('Stages')# set_title方法为子图添加标题ax.set_title('My first matplotlib plot')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LPSqU0kk-1669683258064)(/static/aCpzCrcrPy7evEDNKcdxBW/image.png?auth_key=1669683251-7FqfYxwrsJS2afTTug8nbd-0-db9a631a66dfba2d3a7fdf75588ce66d)]

修改y轴由相同的过程组成,只需要将例子中的x替换为y。axes类由一个set方法允许将批量设置plot属性。对于前面的例子,我们也可以写成:

ax.set(title='My first matplotlib plot', xlabel='Stages')

添加图例

图例是识别绘图元素的另一个关键元素。有几种方法添加图例。最简单的方法是在添加plot的每个部分时传递label参数:

fig, ax = plt.subplots()ax.plot(np.random.randn(1000).cumsum(), color='black', label='one') # 绘制标签为'one'的黑色线图ax.plot(np.random.randn(1000).cumsum(), color='red', linestyle='dashed', label='two') # 绘制标签为‘two'的红色虚线线图ax.plot(np.random.randn(1000).cumsum(), color='blue', linestypel='dotted', label='three') # 绘制标签为‘two'的蓝色点线图# 设置完label后,调用ax.legend方法会自动创建图例ax.legend()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vb5ineu7-1669683258064)(/static/aDHDQfEaeNCP31zS9NvC1i/image.png?auth_key=1669683251-hVvLjgibTJi6s6pWLk5CAE-0-89bdb89b76bf77d2f91fd009a1c20c53)]

legend方法还有别的参数,如位置loc参数。有关详细信息,可以使用ax.legend?查看文档字符串。

loc参数告诉matplotlib图例的放置位置,默认为’best’,它会尝试选择最不偏僻的位置。如果要从图例中排除一个或多个元素,就不设置label或者设置label=‘nolegend’)

注释和子图绘制

除了标准plot类型之外,你可能还希望绘制自己的注释,这些注释可能由文本、箭头或其他形状组成。你可以使用text,arrow和annotate函数添加注释和文本。

# 使用text函数会在plot的给定坐标(x, y)上绘制文本:ax.text(x, y, 'Hello world!', family='monospace', fontsize=10)

注释可以绘制正确排列的文本和箭头。例如,让我们绘制自以来收盘的标准普尔500指数价格(从雅虎财经获得),并用-金融危机的一些重要日期对其进行注释。你可以在Jupyter notebook的单个cell中运行此代码示例。结果参见图9.11:

from datetime import datetimefig, ax = plt.subplots() # 创建绘图窗口和AxesSubplot对象data = pd.read_csv('examples/spx.csv', index_col=0, parse_date=True) # 导入数据,第0列是索引列,并且按照datetime解析spx = data['SPX'] # 获取'SPX'列对应的Seriesspx.plot(ax=ax, color='black') # 根据Series spx绘图,其中ax为需要传入axes对象crisis_data = [(datetime(, 10, 11), 'Peak of bull market'),(datetime(, 3, 12), 'Bear Stearns Fails'),(datetime(, 9, 15), 'Lehman Bankruptcy')] # 元组数组from date, label in crisis_data:ax.annotate(label, xy=(date, spx.asof(date) + 75), # label为要标注的文字,xy为被标注的坐标点,75的单位是点xytext=(date, spx.asof(date) + 225), # xytext为注释文字的坐标位置arrowprops=dict(facecolor='black', headwidth=4, width=2, headlength=4), # 箭头参数horizontalalignment='left', verticalalignment='top') # 水平对齐方式为左对齐,垂直对齐方式为上对齐# series.asof函数会返回给定索引对应的值,如果没有给定索引,则会返回上面最近的一个索引的值# 箭头参数中,headwidth是箭头底部宽度,width是箭头宽度,headlength是箭头长度as.set_xlim(['1/1/', '1/1/']) # 将x轴限定在['1/1/', '1/1/']区间内as.set_ylim([600, 1800]) # 将y轴限定在[600, 1800]区间内as.set_title('Important dates in the - financial crisis'); # 设置标题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-61EFioBZ-1669683258065)(/static/f1J5TX6UqyVd3Edm1ttBM2/image.png)]

绘制形状需要更加小心。matplotlib具有许多常见形状的对象,称为patches。其中一些,如矩形和圆,可以在matplotlib.pypot中找到,但完整集位于matplotlib.patches中。

要将形状添加到绘图中,需要创建patch对象,并通过传递patch对象到ax.add_patch中,将它添加到子图中(见图9.12):

fig, ax = plt.subplots()rect = plt.Rectangle((0.2, 0.75), 0.4, 0.15, color='black', alpha=0.3) # 绘制长0.4,宽0.15的黑色矩形,基点(左下角点)坐标为在(0.2, 0.75)的位置circ = plt.Circle((0.7, 0.2), 0.15, color='blue', alpha=0.3) # 绘制半径为0.15的蓝色圆,基点(圆心点)坐标为在(0.7, 0.2)的位置pgon = plt.Polygon([[0.15, 0.15], [0.35, 0.4], [0.2, 0.6]], color='green', alpha=0.5) # 绘制绿色多边形ax.add_patch(rect) # 将patch对象添加到子图中ax.add_patch(circ)ax.add_patch(pgon)plt.close("all")

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8ZZ7KEHe-1669683258065)(/static/hoyMwhn1gTwzZ2GWQSb2tc/image.png)]

将图片保存到文件

你可以使用figure对象的savefig实例方法将图片保存到文件。例如,要保存一张图片的SVG版本,只需要键入

fig.savefig('figpath.svg')

文件类型是从文件扩展名推断出来的。因此,如果你要用.pdf保存,则会得到pdf文件。

# 图片发布的一个重要参数是dpi,它表示每英寸长度内的像素点数。fig.savefig('figpath.png', dpi=400) # 获得400dpi的png图片

下表是有关savefig参数的描述。

[表]一些fig.savefig参数

matplotlib配置

matplotlib为准备印刷的图形配置了配色方案和默认值。幸运的是,几乎所有默认行为都可以通过全局参数进行自定义,这些参数控制图形大小、子图间距、颜色、字体大小、网络样式等。从Python以编程方式修改配置的一种方法是使用rc方法:

# 要将全局默认图形大小设置成10*10,可以输入plt.rc('figure', figsize=(10, 10))# 所有当前配置都可以在plt.rcParams字典中找到,并且可以通过调用plt.redefaults()函数将它们还原为默认值# rc方法的第一个参数是要自定义的组件,如'figure', 'axes', 'ytick', 'grid', 'legend'等等。之后,可以遵循一系列关键词参数来指示新参数。# 一个方便的方法是作为字典写下参数plt.rc('font', family='mononspace', weight='bold', size=8)

为了进行更广泛的自定义并查看所有选项的列表,matplotlib在matplotlib/mpl数据目录中附带了一个配置文件matplotlibrc。如果你自定义次文件并将其放在标题为.matplotlibrc的主目录中,则每次使用matplotlib时都会加载此文件。

正如我们将在下一节中看到的那种,seaborn软件包有几个内置的主题和样式,这些主题或样式在内部使用matplotlib的配置系统。

9.2用pandas和seaborn画图

matplotlib是一个相当低级的工具。你从图形的基本组件组装图形:数据显示(即图形类型:线、条形、框、散点、等值线等)、图例、标题、刻度标注和其他注释。

在pandas中,我们可能有多个数据列,行以及列标签。pandas本身有内置方法,可以简化从DataFrame和Series对象创建可视化的过程。另一个库是seaborn,这是一个建立在matplotlib上的高级统计图形库。seaborn简化了许多常见可视化类型的创建。

线图

Series和DataFrame有一个plot属性用于创建基本图形。默认情况下,plot()方法生成线图:

s = pd.Series(np.random.standard_normal(10).cumsum(), index=np.arange(0, 100, 10))s.plot()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kDBaFs4C-1669683258065)(/static/2CtPaDXEp54XUHgsfSgHqU/image.png)]

Series对象的索引将传递到matplotlib用于绘制在x轴上,但你可以通过传递use_index=False来禁用它。x轴刻度和限制可以分别用xticks和xlim参数调整,y轴刻度和限制则可以分别用yticks和ylim调整。

下表是Series.plot方法的参数说明。

[表]Series.plot方法的参数

大多数pandas的绘图方法接受一个可选的ax参数,它可以是一个matplotlib子图对象。这使你可以更加灵活地在网格布局中放置子图。

DataFrame的plot方法会将其每列绘制为同一子图上的不同线,从而自动创建图例,如图9.14:

df = pd.DataFrame(np.random.standard_normal((10, 4)).cumsum(0), columns=['A', 'B', 'C', 'D'], index=np.arange(0, 100, 10))plt.style.use('grayscale') # 用plt.style.use('grayscale')切换到更适合黑白出版物的配色方案df.plot()# plot属性包含一系列方法用于不同的图形类型。例如,df.plot()等效于df.plot.line()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UwgA11Ml-1669683258066)(/static/aXBP5YNzuPtnwZpytegyiy/image.png)]

DataFrame有许多选项,允许在如何处理列上具有一定的灵活性。例如,是否将它们全部绘制在同一个子图上还是创建单独的子图。

下表是特定于DataFrame的绘图参数。

[表]特定用于DataFrame的绘图参数

条形图

plot.bar()方法和plot.barh()方法可以分别绘制垂直条形图和水平条形图。在这种情况下,Series或DataFrame索引将分别用作x轴刻度(bar)或y轴刻度(barh),参见图9.15:

fig, axes = plt.subplots(2, 1) # 创建含2*1子图的绘图对象data = pd.Series(np.random.uniform(size=16), index=list('abcdefghijklmnop')) # 创建长为16的Series数据data.plot.bar(ax=axes[0], color='black', alpha=0.7) # 在axes[0]的子图上绘制垂直条形图data.plot.barh(ax=axes[1], color='black', alpha=0.7)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UZts9WPi-1669683258066)(/static/sjADdHbnocitgeszeStqEh/image.png)]

使用DataFrame时,条形图会将每一行的数据分到一组条形上,并为其中每个值分配一个条形

df = pd.DataFrame(np.random.uniform(size=(6, 4)), index=['one', 'two', 'three', 'four', 'five', 'six'],columns=pd.Index(['A', 'B', 'C', 'D'], name='Genus')) # 注意:给DataFrame的列命名的'Genus'会被用于图例的标题df.plot.bar()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nNmm5a5R-1669683258066)(/static/rgS4krosBT5tXm9Kj6hDKR/image.png)]

# 可以通过传递stacked=True从DataFrame创建堆叠的条形图,从而使每行中的值水平堆叠在一起,见图9.17df.plot.barh(stacked=True, alpha=0.5) # 绘制水平堆叠条形图plt.close('all')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-012YUWv5-1669683258067)(/static/ee9T2oXfV68bWGHJPdHVWf/image.png)]

注意:条形图的一个方法是使用value_counts来可视化Series的值频率:s.value_counts().plot.bar()

让我们看一个关于餐厅小费的示例数据集。假设我们想要制作一个堆叠柱线图,显示每天每个派对规模的数据点的百分比。使用read_csv加载数据,并按日期和排队大小创建交叉表(列联表)。pandas.crosstab函数是从两个DataFrame列中计算简单频率表的便捷方法:

tips = pd.read_csv('examples/tips.csv')party_counts = pd.crosstab(tips['day'], tips['size']) # 创建以'day'的不同值为行索引,以'size'的不同值为列索引,表中元素为对应索引下的频数的列联表party_counts = party_counts.reindex(index=['Thur', 'Fri', 'Sat', 'Sun']) # 重排索引party_counts = party_counts.loc[:, 2:5] # 由于1人和6人派对数量不多,所以删除它们,使用loc获得列索引从'2'到'5'的所有列party_pcts = party_counts.div(party_counts.sum(axis='columns'), axis='index') # 跨列求和,并在'index'值相匹的值上计算除法(即行和归一化)party_pcts.plot.bar(stacked=True) # 绘制垂直堆叠条形图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uEIfeMKL-1669683258067)(/static/rdL7SryVV88D5K2VAeUxiS/image.png)]

从图中可以看到,在此数据集中,周末的聚会规模似乎在增加。

对于在进行绘图之前需要聚合或汇总的数据,使用seaborn包(使用conda install seaborn安装)可以使事情变得简单得多。让我们看一下用seaborn计算每天的小费的百分比,结果见图9.19:

import seaborn as snstips['tip_pct'] = tips['tip'] / (tips['total_bill'] - tips['tip']) # 创建一个新的列,用于存放每天的小费占原价的比例sns.barplot(x='tip_pct', y='day', data=tips, orient='h') # x轴是tip_pct,y轴是day,数据来源是tips,绘制水平条形图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ySTy82XS-1669683258067)(/static/xtLYBi5JVPiLbcujVtgBu/image.png)]

seaborn中的绘图函数需要一个data参数,它可以是一个pandas DataFrame。其他参数引用列名。因为在’day’中,小费百分比有多个观测值,所以条形图是tip_pct的平均值。在条形图上画的黑线代表了95%置信区间(这可以通过可选参数进行配置)。

seaborn.barplot有一个hue参数,使我们可以按照额外的分类值进行拆分,结果见图9.20:

sns.barplot(x='tip_pct', y='day', hue='time', data=tips, orient='h') # 额外按照'time'的值进行拆分

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dEsFh7T6-1669683258067)(/static/mFgyaRL1Q769pf6zXgDZTH/image.png)]

注意,seaborn自动更改了图形的美学:默认调色板、绘图背景和网格线颜色。你可以使用seaborn.set_style命令在不同图形外观之间切换:

sns.set_style('whitegrid')sns.set_palette('Greys_r') # 在为黑白打印介质生成绘图时,设置灰色调色板很有用

直方图和密度图

直方图是一种条形图,可提供值频率的离散化显示。数据点被拆分为离散的、间距相等的条柱,并绘制每个条柱中的数据点数。使用之前的小费数据,我们可以使用plot.hist方法制作总账单的小费百分比的直方图,见图9.21:

tips['tip_pct'].plot.hist(bins=50)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bBw4txAK-1669683258068)(/static/2SxnbzKjdyJGy9sk4sNeAa/image.png)]

相关的绘图类型是密度图,它是通过计算可能生成观测数据的连续概率分布的估计而形成的。通常的的过程是将此分布近似为’kernels’的混合,即像正态分布这样的简单分布。因此,密度图也称为核密度估计(KDE)图。通过plot.density可以使用常规的正态混合分布估计得到一个密度图:

tips['tip_pct'].plot.density()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-caOhw2U4-1669683258068)(/static/uiDYSPFmKd3jEE95Nwz9JZ/image.png)]

seaborn通过其他方法可以使直方图和密度图变得更加容易,该方法可以同时绘制直方图和连续密度估计。

# 例如,考虑一个从两个不同标准正态分布的抽样组成的双峰分布,结果见图9.23comp1 = np.random.standard_normal(200)comp2 = 10 + 2 * np.random.standard_normal(200)values = pd.Series(np.concatenate([comp1, comp2]))sns.histplot(values, bins=100, color='black') # 绘制直方图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ejij8Hu2-1669683258068)(/static/r3osMycR7QwQaYjwgdabwV/image.png)]

散点图或点图

点图或散点图是检查两个一维series数据之间关系的有用方法。

# 例如,我们从statsmodels项目中加载macrodata数据集,选择几个变量,然后计算log差异:macro = pd.read_csv('examples/macrodata.csv')data = macro[['cpi', 'm1', 'tbilrate', 'unemp']]trans_data = np.log(data).diff().dropna() # diff()计算DataFrame每个元素与前一个元素的差# 使用seaborn的regplot方法绘制散点图并拟合线性回归线,见图9.24ax = sns.regplot(x='m1', y='unemp', data=trans_data)ax.set_title('Changes in log(m1) versus log(unemp)') # 使用plt.title或者ax.set_title都可以设置标题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KzEM5sDb-1669683258069)(/static/2J6NM1AVS2rvcB54nP1UjX/image.png)]

在探索性数据分析中,能够查看一组变量中的所有散点图是有帮助的;这称为pairs图或者散点图矩阵。从头开始绘制这样的图是一个大工程,因此seaborn有一个方便的pairplot函数,支持沿对角线放置每个变量的直方图和密度估计,结果见图9.25:

sns.pairplot(trans_data, diag_kind='kde', plot_kws={'alpha': 0.2})

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KDDaIr75-1669683258069)(/static/ch3skhWPDuzRcca9gbD3PF/image.png)]

你可能注意到plot_kws参数。这使我们能够将配置选项传递给对角线外元素上的单个绘图调用。查看seaborn.pairplot文档字符串可以获得更精细的配置选项。

分面网格和分类数据

对于具有其他分组维度的数据集,情况如何?可视化具有许多分类变量的数据的一种方法是使用facet grid,这是一种二维绘图布局,其中数据根据特定变量的不同值在每个轴上的绘图中拆分。seaborn有一个有用的内置函数catplot,可以方便地绘制被分类变量分隔的各种facet grid,结果见图9.26:

sns.catplot(x='day', y='tip_pct', hue='time', col='smoker', kind='bar', data=tips[tips.tip_pct < 1])

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GxGGzt4M-1669683258069)(/static/bSizXCZRHDVK6BofDn9BxP/image.png)]

我们也可以不通过使用不同的条形颜色对’time’分组,而通过为每个time值添加一行来扩展facet grid,结果见图9.27:

sns.catplot(x='day', y='tip_pct', row='time', col='smoker', kind='bar', data=tips[tips.tip_pct < 1])

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4PsgEpib-1669683258069)(/static/4KnDaFPZkjRMEfLku5gNfX/image.png)]

catplot支持其他可能有用的打印类型,具体取决于你尝试显示的内容。例如,箱型图(显示中位数、四分位数和异常值)可以是一种有效的可视化类型,见图9.28:

sns.catplot(x='tip_pct', y='day', kind='box', data=tips[tips.tip_pct < 0.5])

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iJ1mTnym-1669683258070)(/static/7isLRYYBXeiAy1QadTMnxe/image.png)]

9.3其他Python可视化工具

在Python中创建图形的选项很多。自以来,许多开发工作一直集中在创建交互式图形以在Web上发布。借助Altair、Bokeh和Plotly等工具,现在可以在Python中指定用于Web浏览器的动态交互式图形。

为了创建用于打印或者Web的静态图形,建议使用matplotlib和基于matplotlib构建的库,如pandas和seaborn,以满足需求。对于其他可视化要求,了解如何使用其他可用工具之一可能很有用。一本关于数据可视化的优秀书籍是Claus O. Wilke(O’Reilly)的《Fundamentals of Data Visualization》(数据可视化基础),该书有印刷版或网站版。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。