0


【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)
wspace

hspace

分别控制图形宽度和图形高度的百分比,以用作子图之间的间距。这是一个小例子,我将间距一直缩小到零(见图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 坐标的数组以及可选的字符串缩写,指示颜色和线型。例如,要绘制

x

y

绿色破折号的对比,您将执行:

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

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

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

为常用颜色提供了许多颜色缩写,但您可以通过指定其十六进制代码(例如,

'#CECECE'

)来使用光谱上的任何颜色。您可以通过查看文档字符串来查看完整的线条样式

plot

plot?

在 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.legend
label

记号、标签和图例

对于大多数类型的情节装饰,有两种主要的做事方式:使用过程

pyplot

接口(即

matplotlib.pyplot

)和更面向对象的本机 matplotlib API。

pyplot

界面专为交互使用而设计,由

xlim

xticks

和等方法组成

xticklabels

。它们分别控制绘图范围、刻度位置和刻度标签。它们可以通过两种方式使用:

  • 不带参数调用返回当前参数值(例如,plt.xlim()返回当前 x 轴绘图范围)
  • 使用参数调用设置参数值(例如, plt.xlim([0, 10])将 x 轴范围设置为 0 到 10)

所有这些方法都作用于活动的或最近的创建

AxesSubplot

. 每一个对应两个子图对象本身的方法;在这些情况下

xlim

ax.get_xlim

ax.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 轴由相同的过程组成,代

y

x

上述过程。轴类有一个

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

arrow

annotate

函数。使用可选的自定义样式在绘图上的

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 具有表示许多常见形状的对象,称为作为补丁。其中一些,如

Rectangle

Circle

,位于 中

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,我将在本节中对其中的一些进行评论,其余的留给你去探索。

yticks
ylim
plot

大多数 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 轴刻度的值

xlim

x 轴范围(例如,

[0, 10]

ylim

y 轴范围

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_counts

:

s.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) 图。Using

plot.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 上发布的交互式图形。和Bokeh和Plotly等工具,现在可以在 Python 中指定用于 Web 浏览器的动态交互式图形。

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

4 结论

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

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


本文转载自: https://blog.csdn.net/sikh_0529/article/details/127002059
版权归原作者 Sonhhxg_柒 所有, 如有侵权,请联系我们删除。

“【Python】绘图和可视化”的评论:

还没有评论