matplotlib绘图学习笔记

Matplotlib 是 Python 中最受欢迎的数据可视化软件包之一,支持跨平台运行,它是 Python 常用的 2D 绘图库,同时它也提供了一部分 3D 绘图接口。

Matplotlib 生成的图形主要由以下几个部分构成:

  • Figure:指整个图形,您可以把它理解成一张画布,它包括了所有的元素,比如标题、轴线等;
  • Axes:绘制 2D 图像的实际区域,也称为轴域区,或者绘图区;
  • Axis:指坐标系中的垂直轴与水平轴,包含轴的长度大小(图中轴长为 7)、轴标签(指 x 轴,y轴)和刻度标签;
  • Artist:您在画布上看到的所有元素都属于 Artist 对象,比如文本对象(title、xlabel、ylabel)、Line2D 对象(用于绘制2D图像)等。

在这里插入图片描述

1. 安装和导入

使用pip管理器来安装matplotlib库

pip install matplotlib

验证安装:

%pip show matplotlib
Name: matplotlib
Version: 3.7.2
Summary: Python plotting package
Home-page: https://matplotlib.org
Author: John D. Hunter, Michael Droettboom
Author-email: matplotlib-users@python.org
License: PSF
Location: /Users/a200007/work/notebook/d2l-zh/lib/python3.10/site-packages
Requires: python-dateutil, fonttools, contourpy, kiwisolver, cycler, packaging, numpy, pyparsing, pillow
Required-by: d2l
Note: you may need to restart the kernel to use updated packages.

首先导入 matplotlib 包中的 pyplot 模块,并以 as 起个别名方便使用。

import matplotlib.pyplot as plt
import numpy as np

设置中文字体来处理中文乱码:

plt.rcParams['font.sans-serif'] = ['Songti SC']  # 使用   字体
plt.rcParams['axes.unicode_minus'] = False  

Mac下可用的中文字体参考:Mac下中文乱码处理方法

pyplot 模块提供了可以用来绘图的各种函数,包括绘制2D图形、3D图形、直方图、条形图、散点图等,绘图类型如下表所示。

函数名称描述
Plot在坐标轴上画线或者标记
Scatter绘制x与y的散点图
Hist绘制直方图
Bar绘制条形图
Barh绘制水平条形图
Pie绘制饼状图
Boxplot绘制箱型图
his2d绘制2D直方图
Polar绘制极坐标图
Stackplot绘制堆叠图
Stem用来绘制二维离散数据绘制(又称为“火柴图”)
Step绘制阶梯图
Quiver绘制一个二维按箭头(注意:这里可能是Quiver的拼写错误,通常可能是Quiverplot或Quiver,代表箭头图或向量场图)

本文将针对常使用的函数进行介绍,并给出示例。

2. 绘制线条

使用 NumPy 提供的函数 arange() 来生成(0,2π)之间的浮点数序列作为自变量x。

正弦函数是一个周期分布,2* π \pi π正好是一个周期。

x = np.arange(0, np.pi * 2, 0.05)
x
array([0.  , 0.05, 0.1 , 0.15, 0.2 , 0.25, 0.3 , 0.35, 0.4 , 0.45, 0.5 ,
       0.55, 0.6 , 0.65, 0.7 , 0.75, 0.8 , 0.85, 0.9 , 0.95, 1.  , 1.05,
       1.1 , 1.15, 1.2 , 1.25, 1.3 , 1.35, 1.4 , 1.45, 1.5 , 1.55, 1.6 ,
       1.65, 1.7 , 1.75, 1.8 , 1.85, 1.9 , 1.95, 2.  , 2.05, 2.1 , 2.15,
       2.2 , 2.25, 2.3 , 2.35, 2.4 , 2.45, 2.5 , 2.55, 2.6 , 2.65, 2.7 ,
       2.75, 2.8 , 2.85, 2.9 , 2.95, 3.  , 3.05, 3.1 , 3.15, 3.2 , 3.25,
       3.3 , 3.35, 3.4 , 3.45, 3.5 , 3.55, 3.6 , 3.65, 3.7 , 3.75, 3.8 ,
       3.85, 3.9 , 3.95, 4.  , 4.05, 4.1 , 4.15, 4.2 , 4.25, 4.3 , 4.35,
       4.4 , 4.45, 4.5 , 4.55, 4.6 , 4.65, 4.7 , 4.75, 4.8 , 4.85, 4.9 ,
       4.95, 5.  , 5.05, 5.1 , 5.15, 5.2 , 5.25, 5.3 , 5.35, 5.4 , 5.45,
       5.5 , 5.55, 5.6 , 5.65, 5.7 , 5.75, 5.8 , 5.85, 5.9 , 5.95, 6.  ,
       6.05, 6.1 , 6.15, 6.2 , 6.25])

然后使用 sin() 函数计算每个点的 y 值

y = np.sin(x)
y
array([ 0.        ,  0.04997917,  0.09983342,  0.14943813,  0.19866933,
        0.24740396,  0.29552021,  0.34289781,  0.38941834,  0.43496553,
        0.47942554,  0.52268723,  0.56464247,  0.60518641,  0.64421769,
        0.68163876,  0.71735609,  0.75128041,  0.78332691,  0.8134155 ,
        0.84147098,  0.86742323,  0.89120736,  0.91276394,  0.93203909,
        0.94898462,  0.96355819,  0.97572336,  0.98544973,  0.99271299,
        0.99749499,  0.99978376,  0.9995736 ,  0.99686503,  0.99166481,
        0.98398595,  0.97384763,  0.9612752 ,  0.94630009,  0.92895972,
        0.90929743,  0.88736237,  0.86320937,  0.83689879,  0.8084964 ,
        0.7780732 ,  0.74570521,  0.71147335,  0.67546318,  0.6377647 ,
        0.59847214,  0.55768372,  0.51550137,  0.47203054,  0.42737988,
        0.38166099,  0.33498815,  0.28747801,  0.23924933,  0.19042265,
        0.14112001,  0.09146464,  0.04158066, -0.00840725, -0.05837414,
       -0.10819513, -0.15774569, -0.20690197, -0.2555411 , -0.30354151,
       -0.35078323, -0.39714817, -0.44252044, -0.48678665, -0.52983614,
       -0.57156132, -0.61185789, -0.65062514, -0.68776616, -0.72318812,
       -0.7568025 , -0.78852525, -0.81827711, -0.8459837 , -0.87157577,
       -0.89498936, -0.91616594, -0.93505258, -0.95160207, -0.96577306,
       -0.97753012, -0.98684386, -0.993691  , -0.99805444, -0.99992326,
       -0.99929279, -0.99616461, -0.99054654, -0.98245261, -0.97190307,
       -0.95892427, -0.94354867, -0.92581468, -0.90576664, -0.88345466,
       -0.85893449, -0.83226744, -0.80352016, -0.77276449, -0.74007731,
       -0.70554033, -0.66923986, -0.63126664, -0.59171558, -0.55068554,
       -0.50827908, -0.46460218, -0.41976402, -0.37387666, -0.32705481,
       -0.2794155 , -0.23107779, -0.1821625 , -0.13279191, -0.0830894 ,
       -0.03317922])

plot方法可以绘制多个点组成的线条,包括直线、曲线、折线等。下面使用plot方法来绘制正弦曲线。

plt.plot(x, y)
plt.xlabel("角度")
plt.ylabel("正弦")
plt.title("正弦曲线")
plt.show()

在这里插入图片描述

3. 使用figure

使用matplotlib.figure模块可以创建图形对象,图形对象借鉴的是面向对象编程的思想,通过图形对象来调用其它的方法和属性。

  • figure(): 创建图形对象(figure object),并通过图形对象来调用其它的方法和属性,这样能处理多个画布。

    参数说明
    figsize指定画布的大小,(宽度,高度),单位为英寸。
    dpi指定绘图对象的分辨率,即每英寸多少个像素,默认值为80。
    facecolor背景颜色。
    edgecolor边框颜色。
    frameon是否显示边框。
  • add_axes(): 添加坐标轴(绘图区域)对象到画布中,一个figure可以添加多个axes,一个axes就是一个绘图区域。

    对象的位置由参数rect决定, 形如 [left, bottom, width, height] ,它表示添加到画布中的矩形区域的左下角坐标(x, y),以及宽度和高度。
    比如 [ 0.1, 0.1, 0.8, 0.8],它代表着从画布 10% 的位置开始绘制, 宽高是画布的 80%。

fig = plt.figure()
x = np.arange(0, np.pi * 2, 0.05)
main_ax = fig.add_axes([0, 0, 1, 1])
sub_ax = fig.add_axes([0.55, 0.65, 0.3, 0.3])
main_ax.plot(x, np.sin(x), "b-")
sub_ax.plot(x, np.cos(x), "r--")
main_ax.set_title("sin")
sub_ax.set_title("cos")
fig.show()

在这里插入图片描述

axes对象有如下属性/函数可以使用:

函数名称描述
Text向轴添加文本
Title设置当前轴的标题
Xlabel设置x轴标签
Xlim获取或者设置x轴区间大小
Xscale设置x轴缩放比例
Xticks获取或设置x轴刻标和相应标签
Ylabel设置y轴的标签
Ylim获取或设置y轴的区间大小
Yscale设置y轴的缩放比例
Yticks获取或设置y轴的刻标和相应标签
grid开启网格
xticklabels获取或设置坐标刻度标签

ax.plot(x, y, kwargs): 将x和y两个数组组成的坐标点绘制成线,一个plot是一个线条,可以多个线条叠加。kwargs常用参数有:

  • linewidth: 线宽,单位为像素
  • linestyle: 线形,如实线、虚线等,线型代码见下表
    字符描述
    ‘-’实线
    ‘–’虚线
    ‘-.’点划线
    ‘:’虚线(注意:Markdown中’:'通常不表示虚线)
    ‘H’六角标记(注意:Markdown中’H’通常不表示图形标记)
  • marker: 坐标点形状,如圆点、方形等,标记符号代码见下表
    标记符号描述
    ‘.’点标记
    ‘o’圆圈标记
    ‘x’'X’标记
    ‘D’钻石标记
    ‘H’六角标记
    ‘s’正方形标记
    ‘+’加号标记
  • markersize: 点的像素大小,例如:10
  • color: 颜色,如red、blue等,颜色代码见下表
    字符颜色
    ‘b’蓝色
    ‘g’绿色
    ‘r’红色
    ‘c’青色
    ‘m’品红色
    ‘y’黄色
    ‘k’黑色
    ‘w’白色

4. legend绘制标签

ax.legend(labels, loc)
  • labels 是一个字符串序列,用来指定标签的名称,一般每个plot都应该有一个标签名称。
  • loc 是指定图例位置的参数,其参数值可以用字符串或整数来表示;

loc 参数的表示方法,分为字符串和整数两种,如下所示:

位置字符串表示整数数字表示
自适应Best0
右上方upper right1
左上方upper left2
左下lower left3
右下lower right4
右侧right5
居中靠左center left6
居中靠右center right7
底部居中lower center8
上部居中upper center9
中部center10

y = [1, 4, 9, 16, 25,36,49, 64]
x1 = [1, 16, 30, 42,55, 68, 77,88]
x2 = [1,6,12,18,28, 40, 52, 65]
fig = plt.figure()               # 图形对象
# axes相当于一个坐标轴,一个图形里可以有多个坐标轴
# [left, bottom, width, height]
# 0: 坐标轴的左边缘与图形对象左边缘对齐
# 0: 坐标轴的下边缘与图形对象下边缘对齐
# 1: 坐标轴的宽度占整个图形对象的100%
# 1: 坐标轴的高度占整个图形对象的100%
ax: plt.Axes = fig.add_axes([0, 0, 1, 1]) 
ax.plot(x1, y, "y.--")           # 表示:黄色、点、虚线, 或者使用:color='y', marker='.', linestyle='--', 
ax.plot(x2, y, "go-")            # 表示:绿色、圆圈、实线,或者使用:color='g', marker='o', linestyle='-'
ax.legend(labels=("线1", "线2"),loc = "lower right")

plt.show()

在这里插入图片描述

5. 绘制子图

subplot: 绘制子图,均等的分割画布。函数定义: plt.subplot(nrows, ncols, index)

nrows 与 ncols 表示要划分成几行几列个子区域,index用来选定此次在哪个子区域绘制(初始值为1)

subplot函数像是在不同画布之间切换,subplot(2, 1, 1)表示在画布上划分成两行一列,当前画布为第一行第一个。


plt.subplot(211)
plt.plot([1,2,3], "y.--")
plt.subplot(212)
plt.plot(range(12), "bo:")
plt.show()

在这里插入图片描述

除subplot函数外,使用figure对象的subplots(nrows, ncols)函数也可以管理子图,此方法能同时创建图形figure对象和画布子区域。

  • nrows 与 ncols 表示两个整数参数,它们指定子图所占的行数、列数。
  • axes 对象的数量等于 nrows * ncols,例如 2 行 2 列表示4个子图。且每个 axes 对象均可通过索引值访问(从1开始)。
  • figsize用于设定图形的整体大小为12x10英寸。

作为对比,subplot() 只是创建一个包含子图区域的画布,subplots() 既创建了一个包含子图区域的画布,又创建了一个 figure 图形对象,更方便使用。

import numpy as np
x = np.arange(1,5)

fig,a = plt.subplots(2,2, figsize=(8,8))
#绘制平方函数
a[0][0].plot(x,x*x)
a[0][0].set_title('square')

#绘制平方根图像
a[0][1].plot(x,np.sqrt(x))
a[0][1].set_title('square root')
a[0][1].grid(True)
#绘制指数函数
a[1][0].plot(x,np.exp(x))
a[1][0].set_title('exp')
a[1][0].grid(color="b", ls="-.", lw=0.25)
a[1][0].set_xticklabels(['zero','one','two','three'])  #设置x轴刻度标签
#绘制对数函数
a[1][1].plot(x,np.log(x))
a[1][1].set_title('log')
a[1][1].set_ylim(0, 2)
a[1][1].set_xlim(0, 4)
fig.tight_layout()
plt.show()

在这里插入图片描述

6. 双轴

在一些应用场景中,有时需要绘制两个 x 轴或两个 y 轴,这样可以更直观地显现图像。

  • ax.twinx(): 在当前图形上添加一个新的y轴(通常是右侧的y轴),这个新轴与原始y轴共享相同的x轴。这意味着,你可以在相同的x坐标位置上绘制两组不同的y轴数据,每组数据有自己的y轴标签和刻度。
  • ax.twiny(): 在当前图形上添加一个新的x轴(通常是顶部x轴),这个新轴与原始x轴共享相同的y轴。这意味着,你可以在相同的y坐标绘制两组不同的x轴数据,每组数据有自己的x轴标签和刻度。
#创建图形对象
fig = plt.figure()
#添加子图区域
a1 = fig.add_axes([0,0,1,1])
x = np.arange(1,11)
a1.plot(x,np.exp(x))
a1.set_ylabel('exp')
#添加双轴
a2 = a1.twinx()
a2.plot(x, np.log(x),'ro-')
a2.set_ylabel('log')
#绘制图例
fig.legend(labels = ('exp','log'),loc='upper left')
plt.show()

在这里插入图片描述

7. 绘制柱状图

bar(): 绘制柱状图,水平轴 X 指定被比较的类别,垂直轴 Y 则表示具体的类别值。其语法格式如下:

ax.bar(x, height, width, bottom, align)

该函数的参数说明,如下表所示:

参数描述
x一个标量序列,代表柱状图的x坐标。默认x取值是每个柱状图所在的中点位置,或者也可以是柱状图左侧边缘位置。
height一个标量或者是标量序列,代表柱状图的高度。
width可选参数,标量或类数组。柱状图的默认宽度值为 0.8。
bottom可选参数,标量或类数组。柱状图的y坐标默认为None。
align有两个可选项 {“center”, “edge”},默认为 ‘center’。该参数决定x值位于柱状图的位置。
fig = plt.figure()
x = ["1班", "2班", "3班", "4班", "5班"]
y = [65, 75, 67, 61, 82]
ax = fig.add_axes([0, 0, 1, 1])
ax.bar(x, y, 0.5)
ax.set_xlabel("班级")
ax.set_ylabel("平均分")
ax.set_title("二年级各班期末数学平均分统计")
plt.show()

在这里插入图片描述

通过调整柱状图的宽度,可以实现在同一 x 轴位置绘制多个柱状图。您可以将它们设置成不同的颜色,从而使它们更容易区分。下图示例了各班级语文、数学、英语的平均成绩。

y = [[65, 75, 67, 61, 82], [76, 73, 68, 88, 63], [90, 82, 95, 69, 72]]
x = np.arange(1, 6, 1)

ax  = plt.figure().add_axes([0, 0, 1, 1])

ax.bar(x, y[0], color="r", width=0.25, label="语文")
ax.bar(x+0.25, y[1], color="g", width=0.25, label="数学")
ax.bar(x+0.5, y[2], color="b", width=0.25, label="英语")

ax.set_xlabel("班级")
ax.set_ylabel("各科平均分数")
ax.legend(loc="upper right")

plt.show()


在这里插入图片描述

8. 饼状图

pie() 函数可以生成数组中数据的饼状图。饼状图显示一个数据系列中各项目的占项目总和的百分比。

参数描述
X数组序列,数组元素对应扇形区域的数量大小。
labels列表字符串序列,为每个扇形区域备注一个标签名字。
color为每个扇形区域设置颜色,默认按照颜色周期自动设置。
autopct格式化字符串,如 “fmt%pct”,使用百分比的格式设置每个扇形区的标签,并将其放置在扇形区内。
#添加图形对象
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
#使得X/Y轴的间距相等,确保绘制的饼状图是一个正圆形
ax.axis('equal')
#准备数据
langs = ['C', 'C++', 'Java', 'Python', 'PHP']
students = [23,17,35,29,12]
#绘制饼状图
ax.pie(students, labels = langs,autopct='%1.2f%%')
plt.show()

在这里插入图片描述

9. 散点图

散点图用于在水平轴和垂直轴上绘制数据点,它表示了因变量随自变量变化的趋势。通俗地讲,它反映的是一个变量受另一个变量的影响程度。

散点图将序列显示为一组点,其中每个散点值都由该点在图表中的坐标位置表示,也可以设置标记符的颜色或大小。

下面示例,绘制了学生考试成绩的散点图,其中蓝色代表男孩成绩,红色表示女孩的成绩。

girls_grades = [89, 90, 70, 89, 100, 80, 90, 100, 80, 34]
boys_grades = [30, 29, 49, 48, 100, 48, 38, 45, 20, 30]
grades_range = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]

ax = plt.figure().add_axes([0, 0, 1, 1])
ax.scatter(grades_range, girls_grades, color="r", label="girls")
ax.scatter(grades_range, boys_grades, color="b", label="boys")
ax.legend()
ax.set_xlabel("等级范围")
ax.set_ylabel("等级分数")

ax.set_title("散点图")
plt.show()

在这里插入图片描述

10. 等高线

等高线: 二维平面上显示三维图像的方法,适用于需要查看因变量z与自变量x、y之间函数图像变化的场景。

左侧图像绘制了两个变量 x、y ,右侧的颜色柱(colorbar)则表示 x 的取值,颜色越深表示值越小,中间深色部分的圆心点表示 x=0,y=0,z=0。

  • np.meshgrid: 生成网格点坐标矩阵,x的每一行都是xlist的拷贝,y的每一列都是ylist的拷贝,形状均为[100, 100]
  • ax.contourf: 填充等高线颜色
  • fig.colorbar: 添加颜色柱,表示不同颜色对应的数值范围
  • ax.contour:绘制等高线图
  • ax.clabel: 给等高线添加标签
xlist = np.linspace(-3, 3, 100)
ylist = np.linspace(-3, 3, 100)
print("list shape:", xlist.shape, ylist.shape)
x, y = np.meshgrid(xlist, ylist)
print("grid shape:", x.shape, y.shape)
z = np.sqrt(x**2 + y**2)
print(ylist, y)

list shape: (100,) (100,)
grid shape: (100, 100) (100, 100)
[-3.         -2.93939394 -2.87878788 -2.81818182 -2.75757576 -2.6969697
 -2.63636364 -2.57575758 -2.51515152 -2.45454545 -2.39393939 -2.33333333
 -2.27272727 -2.21212121 -2.15151515 -2.09090909 -2.03030303 -1.96969697
 -1.90909091 -1.84848485 -1.78787879 -1.72727273 -1.66666667 -1.60606061
 -1.54545455 -1.48484848 -1.42424242 -1.36363636 -1.3030303  -1.24242424
 -1.18181818 -1.12121212 -1.06060606 -1.         -0.93939394 -0.87878788
 -0.81818182 -0.75757576 -0.6969697  -0.63636364 -0.57575758 -0.51515152
 -0.45454545 -0.39393939 -0.33333333 -0.27272727 -0.21212121 -0.15151515
 -0.09090909 -0.03030303  0.03030303  0.09090909  0.15151515  0.21212121
  0.27272727  0.33333333  0.39393939  0.45454545  0.51515152  0.57575758
  0.63636364  0.6969697   0.75757576  0.81818182  0.87878788  0.93939394
  1.          1.06060606  1.12121212  1.18181818  1.24242424  1.3030303
  1.36363636  1.42424242  1.48484848  1.54545455  1.60606061  1.66666667
  1.72727273  1.78787879  1.84848485  1.90909091  1.96969697  2.03030303
  2.09090909  2.15151515  2.21212121  2.27272727  2.33333333  2.39393939
  2.45454545  2.51515152  2.57575758  2.63636364  2.6969697   2.75757576
  2.81818182  2.87878788  2.93939394  3.        ] [[-3.         -3.         -3.         ... -3.         -3.
  -3.        ]
 [-2.93939394 -2.93939394 -2.93939394 ... -2.93939394 -2.93939394
  -2.93939394]
 [-2.87878788 -2.87878788 -2.87878788 ... -2.87878788 -2.87878788
  -2.87878788]
 ...
 [ 2.87878788  2.87878788  2.87878788 ...  2.87878788  2.87878788
   2.87878788]
 [ 2.93939394  2.93939394  2.93939394 ...  2.93939394  2.93939394
   2.93939394]
 [ 3.          3.          3.         ...  3.          3.
   3.        ]]
fig, ax = plt.subplots(1, 2, figsize=(12, 5))
cp = ax[0].contourf(x, y, z)  
ax[0].contour(x, y, z)  # 
fig.colorbar(cp)

cs = ax[1].contour(x, y, z)
ax[1].clabel(cs, inline=1, fontsize=10)
plt.show()

在这里插入图片描述

11. 3D绘图

Matplotlib 在二维绘图的基础上,构建了一部分较为实用的 3D 绘图程序包,比如 mpl_toolkits.mplot3d,通过调用该程序包一些接口可以绘制 3D散点图、3D曲面图、3D线框图等。

11.1 3D线图

ax.plot3D() 绘制各种三维图形,这些三维图都要根据(x,y,z)三元组来创建

from mpl_toolkits import mplot3d
x = np.linspace(0, 1, 100)
y = np.sin(x * 20)
print(y)
z = np.cos(x * 20)
print(z)
ax = plt.axes(projection="3d")
ax.plot3D(x, y, z, "gray")
ax.set_title("3D线图")
plt.show()
[ 0.          0.20064886  0.39313661  0.56963411  0.72296256  0.84688556
  0.93636273  0.98775469  0.99897117  0.96955595  0.90070545  0.79522006
  0.65739025  0.49282204  0.30820902  0.11106004 -0.09060615 -0.28858706
 -0.47483011 -0.64176014 -0.7825875  -0.89158426 -0.96431712 -0.99782778
 -0.99075324 -0.94338126 -0.85763861 -0.73701276 -0.58640998 -0.41195583
 -0.22074597 -0.0205576   0.18046693  0.37415123  0.55261747  0.7086068
  0.83577457  0.92894843  0.98433866  0.99969234  0.97438499  0.90944594
  0.8075165   0.6727425   0.51060568  0.32770071  0.13146699 -0.07011396
 -0.26884313 -0.45663749 -0.62585878 -0.76962418 -0.88208623 -0.95867071
 -0.99626264 -0.99333304 -0.95000106 -0.86802917 -0.75075145 -0.60293801
 -0.43060093 -0.24074979 -0.0411065   0.16020873  0.35500771  0.53536727
  0.69395153  0.82431033  0.9211415   0.98050658  0.99999098  0.9788022
  0.91780205  0.81947165  0.68781042  0.5281735   0.34705389  0.15181837
 -0.04959214 -0.24898556 -0.43825186 -0.6096929  -0.75633557 -0.87221538
 -0.95261911 -0.99427643 -0.995493   -0.95621934 -0.87805285 -0.76417283
 -0.61921119 -0.44906404 -0.26065185 -0.06163804  0.13988282  0.33571414
  0.51789078  0.67900297  0.81249769  0.91294525]
[ 1.          0.97966323  0.91948007  0.8218984   0.69088721  0.53177518
  0.35103397  0.15601496 -0.04534973 -0.24486989 -0.43443032 -0.60632092
 -0.75355031 -0.87013012 -0.95131866 -0.9938137  -0.9958868  -0.95745366
 -0.88007748 -0.76690542 -0.6225406  -0.45285485 -0.26474988 -0.06587659
  0.13567613  0.33171042  0.51425287  0.67587883  0.8100144   0.91120382
  0.97533134  0.99978867  0.98358105  0.9273677   0.83343502  0.70560358
  0.54907273  0.37020915  0.17628785 -0.0248037  -0.2248864  -0.41582217
 -0.58984498 -0.7398767  -0.859815   -0.94478159 -0.99132055 -0.99753899
 -0.96318398 -0.88965286 -0.7799364  -0.63849716 -0.47108797 -0.28451797
 -0.08637561  0.11527995  0.31224667  0.4965132   0.66058479  0.79778804
  0.90254243  0.97058721  0.99915477  0.98708316  0.93486337  0.84461938
  0.72002171  0.56613821  0.38922786  0.19648623 -0.00424719 -0.20480786
 -0.39703827 -0.57311973 -0.72589037 -0.84913647 -0.93784519 -0.98840841
 -0.99876955 -0.9685072  -0.89885222 -0.79263773 -0.65418385 -0.48912199
 -0.30416581 -0.10683812  0.09483505  0.29265094  0.47856368  0.64501154
  0.78522449  0.89349958  0.96543286  0.99809857  0.99016807  0.94196391
  0.85544675  0.73413553  0.58296441  0.40808206]

在这里插入图片描述

11.2 3D散点图
#创建绘图区域
ax = plt.axes(projection='3d')
#构建xyz
x = np.linspace(0, 1, 100)
y = z * np.sin(20 * z)
z = z * np.cos(20 * z)
ax.scatter3D(x, y, z)
ax.set_title("3D散点图")
plt.show()

在这里插入图片描述

11.3 3D等高线图

ax.contour3D() 可以用来创建三维等高线图

xlist = np.linspace(-6, 6, 100)
ylist = np.linspace(-6, 6, 100)
x, y = np.meshgrid(xlist, ylist)
z = np.sqrt(x**2 + y **2)
ax = plt.axes(projection="3d")
ax.contour3D(x, y, z, 50, cmap="binary")
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
ax.set_title('3D 等高线')
plt.show()

在这里插入图片描述

11.4 3D线框图
# #要绘制函数图像
def f(x, y):
    return np.sin(np.sqrt(x ** 2 + y ** 2))
#准备x,y数据
xlist = np.linspace(-6, 6, 30)
ylist = np.linspace(-6, 6, 30)
# #生成x、y网格化数据
X, Y = np.meshgrid(xlist, ylist)
# #准备z值
Z = f(X, Y)
#绘制图像
fig = plt.figure()
ax = plt.axes(projection='3d')
#调用绘制线框图的函数plot_wireframe()
ax.plot_wireframe(X, Y, Z, color='black')
ax.set_title('wireframe')
plt.show()

在这里插入图片描述

11.5 3D曲面图
  1. np.ones(30)得到的是一个长度为30,值作为1的数组
  2. np.outer(x, y):向量外积,用x的每一行去乘以y的每一列,最终得到的是一个矩阵。与外积对应的是内积,是x和y每个相同位置元素乘积的和,得到的是一个标量。
  3. plot_surface:在3D坐标轴上绘制一个曲面图
    • cmap='viridis’用来指定颜色为渐变色
    • edgecolor=‘none’: 曲面边缘无颜色,使得曲面看起来更加平滑。
# print(np.ones(30))
x = np.outer(np.linspace(-3, 3, 30), np.ones(30))
y = x.T
z = np.sin(np.sqrt(x**2 + y**2))
print(x.shape, y.shape, z.shape)
ax = plt.axes(projection="3d")
ax.plot_surface(x, y, z,cmap='viridis', edgecolor='none')
ax.set_title('Surface plot')

plt.show()
(30, 30) (30, 30) (30, 30)

在这里插入图片描述

Mac下中文乱码处理方法

网上很多解决matplotlib中文字体乱码的问题,基本都是告诉我们去设置SimHei字体, 如下面所示:

plt.rcParams["font.sans-serif"]=["SimHei"] #设置字体
plt.rcParams["axes.unicode_minus"]=False #正常显示负号

但是,在Mac下,这个设置并不能正常显示中文字体, 究其原因,SimHei这个字体在Mac根本不存在。那么,我们如何解决这个问题呢?

首先,我们需要知道Mac下有哪些字体,可以通过下面的代码获得。

import matplotlib.font_manager as fm

# 获取系统中所有字体
font_list = fm.findSystemFonts(fontpaths=None, fontext='ttf')

# 打印字体列表
for font in font_list:
    print(font)
/System/Library/Fonts/Supplemental/NotoSansSiddham-Regular.ttf
/System/Library/Fonts/Supplemental/NotoSansHanifiRohingya-Regular.ttf
/System/Library/Fonts/Supplemental/Courier New Bold Italic.ttf
/System/Library/Fonts/Supplemental/Songti.ttc
……

这时只列出了字体文件,但我们需要的是字体名称,所以写了以下方法来打印可用的字体名称。

ttf是一种字体文件格式,而ttc是几个字体文件的合集,两者需要不同的加载方式。

from fontTools.ttLib import TTCollection
from fontTools.ttLib import TTFont

def ttc_names(font_path): 
    # 打开字体文件
    ttc = TTCollection(font_path)
    font_names = set()
    # 遍历每一个子字体
    for font in ttc.fonts:
        for record in font['name'].names:
            if record.nameID == 1:
                font_names.add(record.toStr())
    return font_names

def ttf_names(font_path):
        # 打开字体文件
    font = TTFont(font_path)

    # 获取所有字体家族名称
    font_names = set()
    for record in font['name'].names:
        if record.nameID == 1:
            font_names.add(record.toStr())
    return font_names

def font_names(font_path:str):
    try:
        if font_path.endswith(".ttf"):
            return ttf_names(font_path)
        elif font_path.endswith(".ttc"):
            return ttc_names(font_path)
        else:
            return "unknown"
    except UnicodeDecodeError:
        return "unknown"
        
# 打印字体列表
for font in font_list:
    print(font, "--->", font_names(font))

系统的字体很多,就不一一列举了,只打印中文相关的字体:

/System/Library/Fonts/Supplemental/Songti.ttc ---> {'Songti TC', 'Songti SC', '宋體-繁', 'STSong', '华文宋体', '宋體-簡', '宋体-繁', '宋体-简'}
/System/Library/Fonts/STHeiti Light.ttc ---> {'黒体-簡', '黑体-简', '黒体-繁', 'Heiti SC', '黑體-繁', '黑體-簡', '黑体-繁', 'Heiti-간체', 'Heiti TC', 'Heiti-번체'}
/System/Library/Fonts/Hiragino Sans GB.ttc ---> {'冬青黑體簡體中文', '冬青黑体简体中文', '冬青黑体简体中文 W3', '.Hiragino Sans GB Interface', '冬青黑體簡體中文 W6', '冬青黑體簡體中文 W3', 'Hiragino Sans GB W6', 'Hiragino Sans GB W3', 'Hiragino Sans GB', '冬青黑体简体中文 W6'}
/System/Library/Fonts/PingFang.ttc ---> {'PingFang TC', '.蘋方-簡', '蘋方-港', '.蘋方-港', '.苹方-简', '蘋方-繁', '苹方-港', '苹方-繁', '.PingFang HK', '.PingFang TC', '.蘋方-繁', '.苹方-港', '.PingFang SC', 'PingFang SC', 'PingFang HK', '蘋方-簡', '.苹方-繁', '苹方-简'}

每一条字体中有多个字体名称,本质上是同一个字体家族中的不同变体,例如:

  • ‘Songti TC’ 和 ‘宋體-繁’ 通常指的是繁体中文。
  • ‘Songti SC’ 和 ‘宋體-簡’ 通常指的是简体中文。
  • ‘宋体-繁’ 和 ‘宋体-简’:简体中文环境下对繁体和简体中文宋体的直接称呼。

我们选择其中一种字体名称(如:‘Songti SC’)来作为matplotlib的中文字体即可。

参考资料:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

沉下心来学鲁班

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

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

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

打赏作者

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

抵扣说明:

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

余额充值