2.3 Matplotlib库基础

Matplotlib库是一个非常出色的数据可视化工具包,它也是Anaconda自带的,无须单独安装。本节就来讲解Matplotlib库的基本用法和常用技巧。

2.3.1 基本图表绘制

在绘制图表之前要先引入Matplotlib库,相应的代码通常写成“import matplotlib.pyplotas plt”,这是为了给库设置简称,之后使用plt作为前缀调用所需函数即可绘制图表。

例如,plt.plot()函数用于绘制折线图,plt.bar()函数用于绘制柱形图,plt.pie()函数用于绘制 饼图等。本小节以折线图、柱形图、散点图和直方图为例讲解图表的基本绘制方法。

1.绘制折线图

使用plt.plot()函数可以绘制折线图,演示代码如下。

import matplotlib.pyplot as plt
x = [1, 2, 3]
y = [2, 4, 6]
plt.plot(x, y)  # 绘制折线图
plt.show()  # 展示图形 注意最后要用plt.show()来展示绘制效果

如果想让x和y之间在数学上存在关联,但列表又不太容易进行数学运算,就可以通过NumPy库引入一维数组进行数学运算,代码如下

import numpy as np
import matplotlib.pyplot as plt

x1 = np.array([1, 2, 3])

# 第1条线:y = x + 1
y1 = x1 + 1
plt.plot(x1, y1)  # 使用默认参数绘制

# 第2条线:y = x*2
y2 = x1 * 2
# color为颜色;linewidth为线宽,单位为像素;linestyle为线型,默认为实线,“--”表示虚线
plt.plot(x1, y2, color='red', linewidth=3, linestyle='--')

plt.show()

这里利用NumPy库生成一个一维数组x1,并利用数组的可运算性生成y1和y2,将两条线绘制在一张图表上

2.绘制柱形图

使用plt.bar()函数可以绘制柱形图,演示代码如下。

 import matplotlib.pyplot as plt
 x = [1, 2, 3, 4, 5]
 y = [5, 4, 3, 2, 1]
 plt.bar(x, y)
 plt.show()

3.绘制散点图

使用plt.scatter()函数可以绘制散点图,演示代码如下。

 import matplotlib.pyplot as plt
 import numpy as np

 x = np.random.rand(10)
 y = np.random.rand(10)
 plt.scatter(x, y)
 plt.show()

4.绘制直方图

直方图分为频数直方图和频率直方图,横坐标为相关数据,纵坐标为该数据出现的频数或频率。使用plt.hist()函数可以绘制直方图,演示代码如下。

 import matplotlib.pyplot as plt
 import numpy as np

 # 随机生成10000个服从标准正态分布的数据
 data = np.random.randn(10000)

  #  绘制频数直方图:bins为颗粒度,即直方图的柱形数量;edgecolor为柱形的边框颜色
 plt.hist(data, bins=40, edgecolor='black')

 plt.show()

其中x轴表示随机生成的数据,y轴则表示该数据出现的次数,即频数。

此外,若想绘制频率直方图,可以设置density参数为1。

补充知识点:用pandas库绘制图表对于用pandas库创建的数据表,有更便捷的方法来绘制图表,不过这种方法在本质上还是通过pandas库调用Matplotlib库,演示代码如下。

 # 这种方法只适用于pandas库创建的DataFrame,不适用于NumPy库创建的数组
import pandas as pd
df = pd.DataFrame(data)  # 将前面绘制直方图时使用的data数组转换成DataFrame格式
df.hist(bins=40, edgecolor='black')

array([[<Axes: title={'center': '0'}>]], dtype=object)

这种方法可以快速绘制和之前一样的直方图。因为这里的df只有一列,所以可以直接写df,如果df有多列,那么就需要指明用哪一列绘制直方图,写成df['列名'].hist()。该技巧在14.3.2小节中绘制电影评分频数直方图时会用到。

除了df.hist()函数,还可以使用pandas库中的通用绘图代码绘制图表,代码如下。

 df.plot(kind='hist')

这里通过设置kind参数为hist来绘制直方图。通过更改kind参数,还可以快速绘制其他类型的图表。先创建一个DataFrame格式的二维表格df,代码如下。

import pandas as pd
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用于正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False
df = pd.DataFrame([[8000, 6000], [7000, 5000], [6500, 4000]],
columns=['人均收入', '人均支出'], index=['北京', '上海', '广州'])
df

同时绘制折线图和柱形图的代码如下。

df['人均收入'].plot(kind='line')  # 设置kind为line表示绘制折线图,不设置则默认绘制折线图
df['人均收入'].plot(kind='bar')  # 设置kind为bar表示绘制柱形图

因为df有多列,所以要先通过df['列名']的方式指明需要绘图的列数据

此外,设置kind参数为pie,则可以绘制饼图,如下左图所示;设置kind参数为box,则可以绘制箱体图,如下右图所示。

2.3.2 数据可视化

常用技巧本小节主要讲解数据可视化过程中常用的一些技巧,包括添加文字说明、添加图例、设置双坐标轴、设置图表大小、设置x轴刻度的角度、解决中文显示问题、绘制多图。

1.添加文字说明

使用plt.title()函数为图表添加标题,使用plt.xlabel()和plt.ylabel()函数分别为x轴和y轴添加标签,代码如下。

 import matplotlib.pyplot as plt

 x = [1, 2, 3]
 y = [2, 4, 6]
 plt.plot(x, y)
 plt.title('TITLE')  # 添加图表标题
 plt.xlabel('X')  # 添加x轴标签
 plt.ylabel('Y')  # 添加y轴标签
 plt.show()  # 显示图表
2.添加图例

使用plt.legend()函数给图表添加图例,添加前需要设置好label(标签)参数,代码如下。

import numpy as np
 import matplotlib.pyplot as plt

 # 第1条线:设置label(标签)为“y = x + 1”
 x1 = np.array([1, 2, 3])
 y1 = x1 + 1
 plt.plot(x1, y1, label='y = x + 1')

 # 第2条线:设置label(标签)为“y = x*2”
 y2 = x1*2
 plt.plot(x1, y2, color='red', linestyle='--', label='y = x*2')

 plt.legend(loc='upper left')  # 设置图例位置为左上角
 plt.show()

若要修改图例的位置,可以修改loc参数的值,如'upperright'代表右上角,'lower right'代表右下角。

3.设置双坐标轴

从前面的介绍可知,可以在一张图表里绘制两条线,但如果两条线的取值范围相差较大,那么绘制出的图表效果会不美观,此时需要采用双坐标轴来呈现图表,即为两条线各自绘制y轴。在绘制第1条线的代码之后添加如下代码,即可设置双坐标轴。 plt.twinx()

需要注意的是,如果设置了双坐标轴,那么每绘制一次图表就得添加一次图例,而不能在最后统一添加图例。这里以y=x和y=x2为例,演示如何设置双坐标轴,代码如下。

 import numpy as np
 import matplotlib.pyplot as plt

 # 第1条线:设置label(标签)为“y = x”
 x1 = np.array([10, 20, 30])
 y1 = x1
 plt.plot(x1, y1, color='red', linestyle='--', label='y = x')
 plt.legend(loc='upper left')  # 设置该图表图例在左上角

 plt.twinx()  # 设置双坐标轴

 # 第2条线:设置label(标签)为“y = x^2”
 y2 = x1*x1
 plt.plot(x1, y2, label='y = x^2')
 plt.legend(loc='upper right')  # 设置该图表图例在右上角

 plt.show()
4.设置图表大小
plt.rcParams['figure.figsize'] = (8, 6)

第1个元素代表长,第2个元素代表宽,这里的数字8和6分别代表800像素和600像素。

5.设置x轴刻度的角度

如果x轴因为刻度内容较多,导致刻度太密,不便于阅读,可以通过设置刻度的角度来进行调节,代码如下。其中45表示45°,可以根据需要更改为其他数值。

plt.xticks(rotation=45)
6.解决中文显示问题

注意:在使用 Matplotlib 绘图时,出现“UserWarning: Glyph missing from font”警告,通常是因为默认字体不支持中文字符。由于更改字体会导致显示不出负号“-”,需要将配置文件中的axes.unicode_minus参数设置为False。为了解决这个问题,可以通过以下几种方法设置合适的字体:

  1. 设置全局字体:在绘图代码中添加以下两行代码,以设置中文字体为黑体(SimHei)并解决负号显示问题:
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用于正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用于正常显示负号,解决负号“-”显示为方块的问题
  1. 修改配置文件:如果希望永久解决这个问题,可以直接修改 Matplotlib 的配置文件 matplotlibrc。找到该文件并将 font.family 设置为 SimHei,这样每次绘图时都能自动使用该字体。
  • 找到配置文件: 首先,你需要找到当前使用的 matplotlibrc 文件的位置。
import matplotlib
print(matplotlib.matplotlib_fname())
  • 备份配置文件: 在修改之前,建议备份原有的 matplotlibrc 文件,以防需要恢复到原始设置。
  • 修改配置文件: 打开 matplotlibrc 文件,你可以使用任何文本编辑器进行修改。在文件中找到以下行:
#font.family: sans-serif

去掉前面的 # 号(如果有的话),然后将其修改为:

font.family: SimHei

另外,为了确保中文字符和负号能够正确显示,也可以添加或修改以下行:

font.sans-serif: SimHei, DejaVu Sans, Liberation Sans, Arial, sans-serif
axes.unicode_minus: False
  • 保存并关闭文件: 保存修改后的 matplotlibrc 文件并关闭文本编辑器。
  • 测试修改效果: 在 Python 环境中运行一段绘图代码,检查中文是否能够正确显示。例如:
python

import matplotlib.pyplot as plt
plt.plot([1, 2, 3], [4, 5, 6])
plt.title("测试标题")
plt.xlabel("横轴")
plt.ylabel("纵轴")
plt.show()

通过以上步骤,你可以将 Matplotlib 的默认字体设置为黑体,从而解决中文显示问题。如果你使用的是非 Windows 系统,可能需要将 SimHei 替换为系统中可用的其他中文字体。

  1. 安装中文字体:如果系统中没有 SimHei 字体,可以下载并安装该字体。将字体文件放入 Matplotlib 的字体库路径中,通常路径为:
<your_python_env>/Lib/site-packages/matplotlib/mpl-data/fonts/ttf

通过以上方法,应该能够解决中文字符显示的问题,避免出现方框或乱码的情况。

7.绘制多图

有时我们需要在一张画布上绘制多个图表,如下图所示。这种效果可以利用Matplotlib库的当前图形(figure)和当前轴(axes)概念来实现,这两个概念对应的就是当前画布及当前子图,在一张画布(figure)上可以绘制多张子图(axes)。绘制多图通常采用subplot()函数或subplots()函数。

首先讲解subplot()函数,它的参数通常表示为一个3位整数,该整数的各位数字分别代表子图的行数、列数及当前子图的序号。例如,subplot(221)表示绘制2行2列的子图(共4张子图),当前绘制的是第1张子图,如下图所示。

 import matplotlib.pyplot as plt
 # 绘制第1张子图:折线图
 ax1 = plt.subplot(221)
 plt.plot([1, 2, 3], [2, 4, 6])

 # 绘制第2张子图:柱形图
 ax2 = plt.subplot(222)
 plt.bar([1, 2, 3], [2, 4, 6])

 # 绘制第3张子图:散点图
 ax3 = plt.subplot(223)
 plt.scatter([1, 3, 5], [2, 4, 6])

 # 绘制第4张子图:直方图
 ax4 = plt.subplot(224)
 plt.hist([2, 2, 2, 3, 4])
(array([3., 0., 0., 0., 0., 1., 0., 0., 0., 1.]),
 array([2. , 2.2, 2.4, 2.6, 2.8, 3. , 3.2, 3.4, 3.6, 3.8, 4. ]),
 <BarContainer object of 10 artists>)

每次在新的子图上画图时,都得调用subplot()

函数,例如,第4张子图就得写成ax4=plt.subplot(224),那么能不能一次性生成多张子图呢?这就需要用到subplots()函数,代码如下。

fig, axes = plt.subplots(nrows=2, ncols=2)
ax1, ax2, ax3, ax4 = axes.flatten()

subplots()函数主要有两个参数:nrows表示行数,ncols表示列数。第1行代码中的plt.subplots(nrows=2,ncols=2)(也可以简写为plt.subplots(2,2))就表示绘制2行2列共4张子图,它会返回两个内容:fig(画布)和axes(子图集合,以数组形式存储各张子图)。

第2行代码使用flatten()函数将子图集合展开,从而获得各张子图,此处已知是4张子图,所以分别用“ax1,ax2,ax3,ax4”代表4张子图,之后即可在这4张子图中画图,演示代码如下。这里采用subplots()函数的简写方式,并通过figsize参数设置图表尺寸为1000×800像素。

 fig, axes = plt.subplots(2, 2, figsize=(10, 8))
 ax1, ax2, ax3, ax4 = axes.flatten()
 ax1.plot([1, 2, 3], [2, 4, 6])  # 绘制第1张子图
 ax2.bar([1, 2, 3], [2, 4, 6])  # 绘制第2张子图
 ax3.scatter([1, 3, 5], [2, 4, 6])  # 绘制第3张子图
 ax4.hist([2, 2, 2, 3, 4])  # 绘制第4张子图

,使用subplot()函数在画布中绘制图表时,每次都要调用该函数来指定位置;而使用subplots()函数只需调用生成子图的ax,就可以一次生成多张子图

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐