【Python】绘图和可视化

  🔎大家好,我是Sonhhxg_柒,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎

📝个人主页-Sonhhxg_柒的博客_CSDN博客 📃

🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝​

📣系列专栏 - 机器学习【ML】 自然语言处理【NLP】  深度学习【DL】

 🖍foreword

✔说明⇢本人讲解主要包括Python、机器学习(ML)、深度学习(DL)、自然语言处理(NLP)等内容。

如果你对这个系列感兴趣的话,可以关注订阅哟👋

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

matplotlib 是一个桌面设计用于创建(主要是二维)出版质量图的绘图包。该项目由 John Hunter 于 2002 年在 Python 中启用了类似 MATLAB 的绘图界面。matplotlib 和 IPython 社区合作简化了 IPython shell(现在是 Jupyter notebook)的交互式绘图。matplotlib 支持所有操作系统上的各种 GUI 后端,此外还可以将可视化导出为所有常见的矢量和光栅图形格式(PDF、SVG、JPG、PNG、BMP、GIF 等)。除了少数图表,本书中几乎所有的图形都是使用 matplotlib 生成的。

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

遵循本章中的代码示例的最简单方法是使用 Jupyter 笔记本中的交互式绘图。要进行设置,请在 Jupyter 笔记本中执行以下语句:

%matplotlib notebook

1 matplotlib API 入门简介

使用 matplotlib,我们使用以下导入约定:

import matplotlib.pyplot as plt

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

In [14]: import numpy as np

In [15]: data = np.arange(10)

In [16]: data
Out[16]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

In [17]: plt.plot(data)

图 1-1。简单线图

虽然 seaborn 和 pandas 等库的内置绘图函数将处理绘图的许多平凡细节,但如果您希望在提供的函数选项之外自定义它们,您将需要了解一些有关 matplotlib API 的知识。

笔记

书中没有足够的篇幅来全面介绍 matplotlib 中功能的广度和深度。教你起床和跑步的绳索就足够了。matplotlib 库和文档是学习高级功能的最佳资源。

图和子图

matplotlib 中的绘图位于一个Figure对象。您可以使用以下命令创建一个新图形plt.figure

fig = plt.figure()

在 IPython 中,一个将出现空的绘图窗口,但在 Jupyter 中,除非我们使用更多命令,否则不会显示任何内容。plt.figure有多种选择;值得注意 的是,figsize如果保存到磁盘,将保证图形具有一定的大小和纵横比。

你不能做一个用空白图绘制。您必须 subplots使用以下方法创建一个或多个add_subplot

ax1 = fig.add_subplot(2, 2, 1)

这意味着该图形应该是 2 × 2(总共最多四个图),我们选择四个子图中的第一个(从 1 开始编号)。如果您创建接下来的两个子图,您最终会得到一个如图1-2的可视化效果:

ax2 = fig.add_subplot(2, 2, 2)

ax3 = fig.add_subplot(2, 2, 3)

图 1-2。带有三个子图的空 matplotlib 图

小费

使用 J 的一个细微差别upyter notebooks 是在评估每个单元格后重置绘图,因此对于更复杂的绘图,您必须将所有绘图命令放在单个笔记本单元格中。

在这里,我们在同一个单元格中运行所有这些命令:

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

当您发出类似的绘图命令plt.plot([1.5, 3.5, -2, 1.6])时,matplotlib 会在最后一个使用的图形和子图上绘制(如果需要,创建一个),从而隐藏图形和子图的创建。因此,如果我们添加以下命令,您将得到类似于图1-3的内容:

plt.plot(np.random.randn(50).cumsum(), 'k--')

图 9-3。单次绘图后的数据可视化

'k--'是一个 样式选项,指示 matplotlib 绘制黑色虚线。fig.add_subplot这里返回的对象AxesSubplot 对象,您可以通过调用每个对象的实例方法直接在其他空子图上绘图(见图1-4):

_ = ax1.hist(np.random.randn(100), bins=20, color='k', alpha=0.3)

ax2.scatter(np.arange(30), np.arange(30) + 3 * np.random.randn(30))

图 1-4。附加绘图后的数据可视化

您可以在matplotlib 文档中找到完整的绘图类型目录。

创建带有子图网格的图形是一项非常常见的任务,因此 matplotlib 包含一个方便的方法plt.subplots,即创建一个新图形并返回一个包含创建的子图对象的 NumPy 数组:

In [26]: fig, axes = plt.subplots(2, 3)

In [27]: axes
Out[27]: 
array([[<matplotlib.axes._subplots.AxesSubplot object at 0x7f8c6e3e1ac8>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x7f8c6e371f28>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x7f8c6e3245f8>],
       [<matplotlib.axes._subplots.AxesSubplot object at 0x7f8c6e34ac88>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x7f8c6e2fa390>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x7f8c6e2a19e8>]],
      dtype=object)

这非常有用,因为axes 数组可以像二维数组一样轻松索引;例如, axes[0, 1]。您还可以分别使用sharex和指示子图应具有相同的 x 轴或 y 轴。sharey这在您比较相同比例的数据时特别有用;否则,matplotlib 会独立自动缩放绘图限制。有关此方法的更多信息,请参见表1-1。

表 1-1。pyplot.subplots 选项
争论描述
nrows子图的行数
ncols子图的列数
sharex所有子图应使用相同的 x 轴刻度(调整xlim将影响所有子图)
sharey所有子图应使用相同的 y 轴刻度(调整ylim将影响所有子图)
subplot_kw传递给add_subplot用于创建每个子图的调用的关键字字典
**fig_kw创建图窗时要使用的其他关键字subplots,例如plt.subplots(2, 2, figsize=(8, 6))

调整子图周围的间距

默认情况下,matplotlib 在子图外部和子图之间留下一定数量的填充。这个间距都是相对于绘图的高度和宽度指定的,因此,如果您以编程方式或使用 GUI 窗口手动调整绘图大小,绘图将自行动态调整。你可以改变间距在对象上使用该subplots_adjust方法Figure,也可用作顶级函数:

subplots_adjust(left=None, bottom=None, right=None, top=None, 
                wspace=None, hspace=None)

wspacehspace分别控制图形宽度和图形高度的百分比,以用作子图之间的间距。这是一个小例子,我将间距一直缩小到零(见图1-5):

fig, axes = plt.subplots(2, 2, sharex=True, sharey=True)
for i in range(2):
    for j in range(2):
        axes[i, j].hist(np.random.randn(500), bins=50, color='k', alpha=0.5)
plt.subplots_adjust(wspace=0, hspace=0)

图 1-5。没有子图间距的数据可视化

您可能会注意到轴标签重叠。matplotlib 不检查标签是否重叠,因此在这种情况下,您需要自己通过指定明确的刻度位置和刻度标签来修复标签(我们将在下面介绍如何执行此操作 部分)。

颜色、标记和线型

Matplotlib的主要plot功能 接受 x 和 y 坐标的数组以及可选的字符串缩写,指示颜色和线型。例如,要绘制xy绿色破折号的对比,您将执行:

ax.plot(x, y, 'g--')

提供这种在字符串中同时指定颜色和线条样式的方法是为了方便;在实践中,如果您以编程方式创建绘图,您可能不希望将字符串组合在一起以创建具有所需样式的绘图。同样的情节也可以更明确地表达为:

ax.plot(x, y, linestyle='--', color='g')

为常用颜色提供了许多颜色缩写,但您可以通过指定其十六进制代码(例如,'#CECECE')来使用光谱上的任何颜色。您可以通过查看文档字符串来查看完整的线条样式plotplot?在 IPython 或 Jupyter 中使用)。

线图可以另外标记以突出显示实际数据点。由于 matplotlib 创建了一个连续的线图,在点之间进行插值,因此有时可能不清楚点的位置。标记可以是样式字符串,必须有颜色,后跟标记类型和线型(见图1-6):

from numpy.random import randn

plt.plot(randn(30).cumsum(), 'ko--')

图 1-6。带标记的线图

这也可以更明确地写成:

plot(randn(30).cumsum(), color='k', linestyle='dashed', marker='o')

对于线图,您会注意到默认情况下后续点是线性插值的。这可以通过以下drawstyle选项进行更改(图1-7):

In [35]: data = np.random.randn(30).cumsum()

In [36]: plt.plot(data, 'k--', label='Default')
Out[36]: [<matplotlib.lines.Line2D at 0x7f8c59dca3c8>]

In [37]: plt.plot(data, 'k-', drawstyle='steps-post', label='steps-post')
Out[37]: [<matplotlib.lines.Line2D at 0x7f8c59dca898>]

In [38]: plt.legend(loc='best')

图 1-7。具有不同绘图样式选项的线图

<matplotlib.lines.Line2D at ...>当你运行它时,你可能会注意到输出。matplotlib 返回引用刚刚添加的绘图子组件的对象。很多时候你可以放心地忽略这个输出。在这里,由于我们将 label参数传递给plot,我们能够创建一个图例来识别每个线使用plt.legend.

笔记

无论您在绘制数据时是否传递了 选项,都必须调用plt.legend(或者 ,如果您有对轴的引用)来创建图例。ax.legendlabel

记号、标签和图例

对于大多数类型的情节装饰,有两种主要的做事方式:使用过程pyplot 接口(即matplotlib.pyplot)和更面向对象的本机 matplotlib API。

pyplot界面专为交互使用而设计,由xlimxticks和等方法组成xticklabels。它们分别控制绘图范围、刻度位置和刻度标签。它们可以通过两种方式使用:

  • 不带参数调用返回当前参数值(例如,plt.xlim()返回当前 x 轴绘图范围)

  • 使用参数调用设置参数值(例如, plt.xlim([0, 10])将 x 轴范围设置为 0 到 10)

所有这些方法都作用于活动的或最近的创建AxesSubplot. 每一个对应两个子图对象本身的方法;在这些情况下 xlimax.get_xlimax.set_xlim。我更喜欢自己使用 subplot 实例方法,以便明确(尤其是在处理多个 subplot 时),但你当然可以使用任何你觉得更方便的方法。

设置标题、轴标签、刻度和刻度标签(Ticks, Labels, and Legends

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

fig = plt.figure()

ax = fig.add_subplot(1, 1, 1)

ax.plot(np.random.randn(1000).cumsum())

图 1-8。用于说明 xticks 的简单图(带标签)

要更改 x 轴刻度,最简单的方法是使用set_xticks和 set_xticklabels。前者指示 matplotlib 在数据范围内放置刻度的位置;默认情况下,这些位置也将是标签。但是我们可以使用以下方法将任何其他值设置为标签set_xticklabels

ticks = ax.set_xticks([0, 250, 500, 750, 1000])

labels = ax.set_xticklabels(['one', 'two', 'three', 'four', 'five'],
                                rotation=30, fontsize='small')

rotation选项将 x 刻度标签设置为 30 度旋转。最后,set_xlabel给出 x 轴的名称set_title子图标题(结果图见图1-9):

In [44]: ax.set_title('My first matplotlib plot')
Out[44]: Text(0.5,1,'My first matplotlib plot')

In [45]: ax.set_xlabel('Stages')

图 1-9。用于说明 xticks 的简单图

修改 y 轴由相同的过程组成,代 yx上述过程。轴类有一个set允许批量设置绘图属性的方法。从前面的例子中,我们也可以有书面:

props = {
    'title': 'My first matplotlib plot',
    'xlabel': 'Stages'
}
ax.set(**props)

添加图例

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

In [46]: from numpy.random import randn

In [47]: fig = plt.figure(); ax = fig.add_subplot(1, 1, 1)

In [48]: ax.plot(randn(1000).cumsum(), 'k', label='one')
Out[48]: [<matplotlib.lines.Line2D at 0x7f8c4c439940>]

In [49]: ax.plot(randn(1000).cumsum(), 'k--', label='two')
Out[49]: [<matplotlib.lines.Line2D at 0x7f8c4c454f60>]

In [50]: ax.plot(randn(1000).cumsum(), 'k.', label='three')
Out[50]: [<matplotlib.lines.Line2D at 0x7f8c4c460438>]

完成此操作后,您可以调用ax.legend()或 plt.legend()自动创建图例。结果图如图1-10所示:

ax.legend(loc='best')

图 1-10。三线图例的简单情节

legend方法还有其他几个位置loc参数的选择。有关更多信息,请参阅文档字符串(带ax.legend?)。

loc告诉_matplotlib 在哪里放置绘图。如果您不挑剔, 'best'这是一个不错的选择,因为它会选择一个最不碍事的位置。要从图例中排除一​​个或多个元素,不通过标签或label='_nolegend_'.

子图上的注释和绘图

除了标准绘图类型,您可能希望绘制自己的绘图注释,其中可能包含文本、箭头或其他形状。您可以添加注释和文本使用text、 arrowannotate函数。使用可选的自定义样式在绘图上的text给定坐标处绘制文本:(x, y)

ax.text(x, y, 'Hello world!',
        family='monospace', fontsize=10)

注释可以绘制适当排列的文本和箭头。例如,让我们绘制自 2007 年以来的标准普尔 500 指数收盘价(从雅虎财经获得),并用 2008-2009 年金融危机的一些重要日期对其进行注释。您可以最轻松地在 Jupyter 笔记本的单个单元格中重现此代码示例。结果见图 1-11:

from datetime import datetime

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)

data = pd.read_csv('examples/spx.csv', index_col=0, parse_dates=True)
spx = data['SPX']

spx.plot(ax=ax, style='k-')

crisis_data = [
    (datetime(2007, 10, 11), 'Peak of bull market'),
    (datetime(2008, 3, 12), 'Bear Stearns Fails'),
    (datetime(2008, 9, 15), 'Lehman Bankruptcy')
]

for date, label in crisis_data:
    ax.annotate(label, xy=(date, spx.asof(date) + 75),
                xytext=(date, spx.asof(date) + 225),
                arrowprops=dict(facecolor='black', headwidth=4, width=2,
                                headlength=4),
                horizontalalignment='left', verticalalignment='top')

# Zoom in on 2007-2010
ax.set_xlim(['1/1/2007', '1/1/2011'])
ax.set_ylim([600, 1800])

ax.set_title('Important dates in the 2008-2009 financial crisis')

图 1-11。2008-2009 年金融危机的重要日期

在这个图中有几个要点需要强调:该ax.annotate方法可以在指定的 x 和 y 坐标处绘制标签。我们用和方法手动设置绘图的开始和结束边界,而不是使用 matplotlib 的默认值set_xlim。 set_ylim最后, ax.set_title补充情节的主要标题。

请参阅在线 matplotlib 库,了解更多可供学习的注释示例。

绘制形状需要更多的关注。matplotlib 具有表示许多常见形状的对象,称为作为补丁。其中一些,如 RectangleCircle,位于 中matplotlib.pyplot,但完整集位于 中matplotlib.patches

要将形状添加到绘图中,请创建补丁对象shp并将其添加到调用子图ax.add_patch(shp)(见图1-12):

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)

rect = plt.Rectangle((0.2, 0.75), 0.4, 0.15, color='k', alpha=0.3)
circ = plt.Circle((0.7, 0.2), 0.15, color='b', alpha=0.3)
pgon = plt.Polygon([[0.15, 0.15], [0.35, 0.4], [0.2, 0.6]],
                   color='g', alpha=0.5)

ax.add_patch(rect)
ax.add_patch(circ)
ax.add_patch(pgon)

图 1-12。由三个不同的补丁组成的数据可视化

如果您查看许多熟悉的绘图类型的实现,您会发现它们是由补丁组装而成。

将绘图保存到文件

您可以保存活动图使用plt.savefig. 该方法等价于图形对象的savefig实例 方法。例如,要保存图形的 SVG 版本,您只需键入:

plt.savefig('figpath.svg')

文件类型是从文件扩展名中推断出来的。因此,如果您 .pdf改为使用,您将获得 PDF。我经常使用几个重要的选项来发布图形:dpi控制每英寸点数的分辨率,以及bbox_inches可以修剪实际数字周围的空白。要获得与 PNG 相同的图,并且图周围的空白最少且 DPI 为 400,您可以:

plt.savefig('figpath.png', dpi=400,bbox_inches='tight')

savefig不必写入磁盘;它还可以写入任何类似文件的对象,例如BytesIO

from io import BytesIO
buffer = BytesIO()
plt.savefig(buffer)
plot_data = buffer.getvalue()

有关. _ _savefig

表 1-2。图.savefig 选项
争论描述
fname包含文件路径或 Python 文件类对象的字符串。图形格式是从文件扩展名中推断出来的(例如,.pdf对于 PDF 或 .png对于 PNG)
dpi以每英寸点数为单位的图形分辨率;默认为 100,但可以配置
facecolor, edgecolor子图外的图形背景颜色;'w'(白色),默认情况下
format要使用的显式文件格式 ( 'png''pdf''svg''ps''eps', ...)
bbox_inches要保存的图形部分;如果'tight'通过,将尝试修剪图形周围的空白区域

matplotlib 配置

matplotlib 来了配置了配色方案和默认设置,主要用于准备要发布的图形。幸运的是,几乎所有默认行为都可以通过一组广泛的全局参数进行自定义,这些参数控制图形大小、子图间距、颜色、字体大小、网格样式等。从 Python 以编程方式修改配置的一种方法是使用rc方法;例如,要将全局默认图形大小设置为 10 × 10,您可以输入:

plt.rc('figure', figsize=(10, 10))

第一个参数rc是您希望自定义的组件,例如'figure''axes''xtick''ytick''grid''legend', 或许多其他参数。之后可以遵循一系列指示新参数的关键字参数。在程序中写下选项的一种简单方法是使用 dict:

font_options = {'family' : 'monospace',
                'weight' : 'bold',
                'size'   : 'small'}
plt.rc('font', **font_options)

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

正如我们将在下一节中看到的,seaborn 包有几个使用 matplotlib 配置系统的内置绘图主题或样式内部。

2 用 pandas 和 seaborn 绘图

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

在 pandas 中,我们可能有多列数据,以及行和列标签。pandas 本身具有内置方法,可简化从 DataFrame 和 Series 对象创建可视化。另一个库是 seaborn,一个统计由创建的图形库迈克尔·瓦斯科姆。Seaborn 简化了许多常见可视化类型的创建。

小费

导入 seaborn 会修改默认的 matplotlib 配色方案和绘图样式,以提高可读性和美观性。即使您不使用 seaborn API,您也可能更喜欢将 seaborn 作为一种简单的方法来导入,以提高一般 matplotlib 绘图的视觉美感。

线图(Line Plots

系列和DataFrame 每个都有一个plot用于制作一些基本绘图类型的属性。默认情况下,plot()使线图(见图1-13):

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

s.plot()

图 1-13。简单系列图

Series 对象的索引被传递给 matplotlib 以在 x 轴上绘图,但您可以通过传递use_index=False. 可以使用xticks和 选项调整 x 轴刻度和范围,使用和xlim分别调整 y 轴。有关选项 的完整列表,请见表1-3,我将在本节中对其中的一些进行评论,其余的留给你去探索。yticksylimplot

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

DataFrame 的plot方法将其每一列绘制为同一子图上的不同线,自动创建图例(见图 9-14):

In [64]: df = pd.DataFrame(np.random.randn(10, 4).cumsum(0),
   ....:                   columns=['A', 'B', 'C', 'D'],
   ....:                   index=np.arange(0, 100, 10))

In [65]: df.plot()

图1-14。简单的 DataFrame 图

plot属性包含用于不同绘图类型的“系列”方法。例如, df.plot()等价于 df.plot.line()。接下来我们将探讨其中的一些方法。

笔记

额外的关键字参数plot传递给相应的 matplotlib 绘图函数,因此您可以通过了解有关 matplotlib API 的更多信息来进一步自定义这些绘图。

表 1-3。Series.plot 方法参数
争论描述
label标签对于情节传奇
ax要绘制的 matplotlib 子图对象;如果没有通过,则使用活动的 matplotlib 子图
style'ko--'要传递给 matplotlib 的样式字符串,如
alpha绘图填充不透明度(从 0 到 1)
kind可以是'area''bar''barh''density''hist''kde''line','pie'
logy在 y 轴上使用对数缩放
use_index将对象索引用于刻度标签
rot刻度标签的旋转(0 到 360)
xticks用于 x 轴刻度的值
yticks用于 y 轴刻度的值
xlimx 轴范围(例如,[0, 10]
ylimy 轴范围
grid显示轴网格(默认开启)

DataFrame 有许多选项,允许在处理列的方式上有一定的灵活性;例如,是将它们全部绘制在同一个子图上还是创建单独的子图。有关这些的更多信息,请参见表1-4。

表 1-4。DataFrame 特定的绘图参数
争论描述
subplots阴谋每个 DataFrame 列在一个单独的子图中
sharex如果subplots=True,共享相同的 x 轴,链接刻度和限制
sharey如果subplots=True,共享同一个 y 轴
figsize要创建为元组的图形大小
title将标题绘制为字符串
legend添加子图图例(True默认情况下)
sort_columns按字母顺序绘制列;默认使用现有列命令

笔记

有关时间序列绘图,请参阅第 11 章

条形图(Bar Plots

plot.bar()和 plot.barh()使_分别是垂直和水平条形图。在这种情况下,Series 或 DataFrame 索引将用作 x ( bar) 或 y ( barh) 刻度(见图1-15):

In [66]: fig, axes = plt.subplots(2, 1)

In [67]: data = pd.Series(np.random.rand(16), index=list('abcdefghijklmnop'))

In [68]: data.plot.bar(ax=axes[0], color='k', alpha=0.7)
Out[68]: <matplotlib.axes._subplots.AxesSubplot at 0x7f8c4c1b9b00>

In [69]: data.plot.barh(ax=axes[1], color='k', alpha=0.7)

图 1-15。水平和垂直条形图

选项color='k'并将 alpha=0.7绘图的颜色设置为黑色,并在填充上使用部分透明度。

使用 DataFrame,条形图将每行中的值组合成一个条形组,并排,每个值。见图1-16:

In [71]: df = pd.DataFrame(np.random.rand(6, 4),
   ....:                   index=['one', 'two', 'three', 'four', 'five', 'six'],
   ....:                   columns=pd.Index(['A', 'B', 'C', 'D'], name='Genus'))

In [72]: df
Out[72]: 
Genus         A         B         C         D
one    0.370670  0.602792  0.229159  0.486744
two    0.420082  0.571653  0.049024  0.880592
three  0.814568  0.277160  0.880316  0.431326
four   0.374020  0.899420  0.460304  0.100843
five   0.433270  0.125107  0.494675  0.961825
six    0.601648  0.478576  0.205690  0.560547

In [73]: df.plot.bar()

图 1-16。DataFrame 条形图

请注意,DataFrame 列上的名称“Genus”用于为图例命名。

我们通过传递从 DataFrame 创建堆叠条形图stacked=True,导致每一行中的值堆叠在一起(见图1-17):

df.plot.barh(stacked=True, alpha=0.5)

图 1-17。DataFrame 堆积条形图

笔记

条形图的一个有用方法是可视化系列的值频率使用value_countss.value_counts().plot.bar()

让我们看一个关于餐厅小费的示例数据集,假设我们想要制作一个堆积条形图,显示每天每个派对规模的数据点百分比。我加载数据使用read_csv并按日期和聚会规模进行交叉制表:

In [77]: tips = pd.read_csv('examples/tips.csv')

In [78]: tips.head()
Out[78]: 
   total_bill   tip smoker  day    time  size
0       16.99  1.01     No  Sun  Dinner     2
1       10.34  1.66     No  Sun  Dinner     3
2       21.01  3.50     No  Sun  Dinner     3
3       23.68  3.31     No  Sun  Dinner     2
4       24.59  3.61     No  Sun  Dinner     4

In [79]: party_counts = pd.crosstab(tips['day'], tips['size'])

In [80]: party_counts
Out[80]: 
size  1   2   3   4  5  6
day                      
Fri   1  16   1   1  0  0
Sat   2  53  18  13  1  0
Sun   0  39  15  18  3  1
Thur  1  48   4   5  1  3

# Not many 1- and 6-person parties
In [81]: party_counts = party_counts.loc[:, 2:5]

然后,进行归一化,使每行总和为 1 并绘制绘图( 见图1-18):

# Normalize to sum to 1
In [82]: party_pcts = party_counts.div(party_counts.sum(1), axis=0)

In [83]: party_pcts
Out[83]: 
size         2         3         4         5
day                                         
Fri   0.888889  0.055556  0.055556  0.000000
Sat   0.623529  0.211765  0.152941  0.011765
Sun   0.520000  0.200000  0.240000  0.040000
Thur  0.827586  0.068966  0.086207  0.017241

In [84]: party_pcts.plot.bar()

图 1-18。每天按规模划分的派对比例

因此,您可以在此数据集中看到周末聚会的人数似乎有所增加。

对于需要在绘制图之前进行聚合或汇总的数据,使用该seaborn包可以使事情变得更加简单。现在让我们看看 seaborn 每天的小费百分比(结果见图1-19):

In [86]: import seaborn as sns

In [87]: tips['tip_pct'] = tips['tip'] / (tips['total_bill'] - tips['tip'])

In [88]: tips.head()
Out[88]: 
   total_bill   tip smoker  day    time  size   tip_pct
0       16.99  1.01     No  Sun  Dinner     2  0.063204
1       10.34  1.66     No  Sun  Dinner     3  0.191244
2       21.01  3.50     No  Sun  Dinner     3  0.199886
3       23.68  3.31     No  Sun  Dinner     2  0.162494
4       24.59  3.61     No  Sun  Dinner     4  0.172069

In [89]: sns.barplot(x='tip_pct', y='day', data=tips, orient='h')

图 1-19。带误差线的每日小费百分比

seaborn 中的绘图函数需要一个data 参数,可以是 pandas DataFrame。其他参数是指列名。因为 中的每个值都有多个观测值day,所以条形图是 的平均值 tip_pct。条上绘制的黑线代表 95% 的置信区间(这可以通过可选参数进行配置)。

seaborn.barplot 有一个hue选项可以让我们按额外的分类值进行拆分(图1-20):

sns.barplot(x='tip_pct', y='day', hue='time', data=tips, orient='h')

图 1-20。每天和时间的小费百分比

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

sns.set(style="whitegrid")

直方图和密度图(Histograms and Density Plots

直方图是一种条形图的离散化显示值频率。数据点被分成离散的、均匀分布的 bin,并绘制了每个 bin 中的数据点数量。使用之前的小费数据,我们可以使用该plot.hist方法 制作总账单中小费百分比的直方图在系列上(见图1-21):

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

图 1-21。小费百分比直方图

相关的绘图类型是密度图,它是通过计算可能已生成观察数据的连续概率分布的估计值而形成的。通常的过程是将这种分布近似为“核”的混合——即,像正态分布这样更简单的分布。因此,密度图也称为核密度估计 (KDE) 图。Usingplot.kde使用 常规的正态混合估计(见图1-22):

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

图 1-22。尖端百分比的密度图

Seaborn 使直方图和密度图更容易通过它的distplot方法,可以同时绘制直方图和连续密度估计。例如,考虑一个由两个不同标准正态分布组成的双峰分布(见图1-23):

comp1 = np.random.normal(0, 1, size=200)

comp2 = np.random.normal(10, 2, size=200)

values = pd.Series(np.concatenate([comp1, comp2]))

sns.distplot(values, bins=100, color='k')

图 1-23。具有密度估计的正态混合的归一化直方图

散点图或点图(Scatter or Point Plots

点图或散点图可能是检查两个一维数据系列之间关系的有用方法。例如,这里我们macrodata从 statsmodels 项目加载数据集,选择一些变量,然后计算对数差异:

In [103]: macro = pd.read_csv('examples/macrodata.csv')

In [104]: data = macro[['cpi', 'm1', 'tbilrate', 'unemp']]

In [105]: trans_data = np.log(data).diff().dropna()

In [106]: trans_data[-5:]
Out[106]: 
          cpi        m1  tbilrate     unemp
198 -0.007904  0.045361 -0.396881  0.105361
199 -0.021979  0.066753 -2.277267  0.139762
200  0.002340  0.010286  0.606136  0.160343
201  0.008419  0.037461 -0.200671  0.127339
202  0.008894  0.012202 -0.405465  0.042560

然后我们可以使用seaborn 的regplot方法,它制作散点图并拟合线性回归线(见图1-24):

In [108]: sns.regplot('m1', 'unemp', data=trans_data)
Out[108]: <matplotlib.axes._subplots.AxesSubplot at 0x7f8c66961978>

In [109]: plt.title('Changes in log %s versus log %s' % ('m1', 'unemp'))

图 1-24。seaborn 回归/散点图

在探索性数据分析中,能够查看一组变量之间的所有散点图是有帮助的;这是众所周知的 作为配对图或散点图矩阵。从头开始制作这样的情节有点工作,所以 seaborn 有一个方便pairplot的函数,它支持沿对角线放置每个变量的直方图或密度估计(结果见图1-25):

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

图 1-25。statsmodels 宏数据的配对图矩阵

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

分面网格和分类数据

数据集呢我们在哪里有额外的分组维度?可视化具有许多分类变量的数据的一种方法是使用分 面网格。Seaborn 有一个有用的内置 factorplot函数简化了多种刻面图的制作(结果见图1-26):

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

图 1-26。按天/时间/吸烟者的小费百分比

除了按构面内的不同条形颜色进行分组外,我们还可以通过为每个值'time'添加一行来扩展构面网格(图1-27):time

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

图 1-27。tip_pct 按天计算;按时间/吸烟者划分

factorplot支持其他可能有用的绘图类型,具体取决于您要显示的内容。例如,箱线图(显示中位数、四分位数和异常值)可以是一种有效的可视化类型(图1-28):

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

图 1-28。每日tip_pct箱线图

您可以使用更多创建自己的分面网格图一般seaborn.FacetGrid类。请参阅seaborn 文档更多的。

3 其他 Python 可视化工具

与 open 一样常见来源,有很多用于在 Python 中创建图形的选项(太多无法列出)。自 2010 年以来,许多开发工作都集中在创建用于在 Web 上发布的交互式图形。和BokehPlotly等工具,现在可以在 Python 中指定用于 Web 浏览器的动态交互式图形。

对于为打印或网络创建静态图形,我建议默认使用 matplotlib 和附加库,如 pandas 和 seaborn 以满足您的需要。对于其他数据可视化要求,学习其他可用工具之一可能会很有用。我鼓励您探索生态系统,因为它会继续参与并创新未来。

4 结论

本章的目的是让您了解一些使用 pandas、matplotlib 和 seaborn 的基本数据可视化。如果直观地传达数据分析的结果在您的工作中很重要,我鼓励您寻找资源以了解有关有效数据可视化的更多信息。这是一个活跃的研究领域,您可以使用许多在线和印刷形式的优秀学习资源进行练习。

在下一章中,我们将注意力转向使用 pandas 进行数据聚合和分组操作。

  • 6
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sonhhxg_柒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值