Part I. Matplotlib MatplotlibMatplotlib 是一个 Python 的 2D 绘图库,它以各种硬拷贝格式和跨平台的交互式环境生成出版质量级别的图形。 安装 matplotlib 的最简单方法是使用 pip。 pip 是一个现代的,通用的 Python 包管理工具。提供了对 Python 包的查找、下载、安装、卸载的功能。
命令提示符(cmd)或 Linux shell 中键入以下命令: 使用 matplotlib 库需要首先将其导入代码: import matplotlib.pyplot as plt
每个 pyplot 函数都会对图形进行一些设置 e.g.: 创建图形:plt.figure()
在图形中创建绘图区域:plt.subplot(1, 1)
在绘图区域中绘制一些线:plt.plot([0, 1], [0, 1], label='line')
用标签等装饰绘图:plt.legend()
无论何时使用 matplotlib 绘图,都应有两行主要代码: 图的类型 定义条形图、折线图等图的类型:plt.plot()
、plt.bar()
显示图表 显示图形的代码:plt.show()
matplotlib 可以让你轻松完成任务,只需几行代码即可生成绘图、直方图、条形图、误差图、散点图等: 从一个简单的例子开始1 2 3 4 5 6 7 import matplotlib.pyplot as pltx = [0 , 1 , 2 , 3 , 4 , 5 ] y = [0 , 1 , 4 , 9 , 16 , 25 ] plt.plot(x, y) plt.show()
注意:如果为 plot() 命令提供单个列表或数组,则 matplotlib 假设它是一个 y 值序列,并且自动生成 x 值。 1 2 3 4 import matplotlib.pyplot as pltplt.plot([1 , 2 , 3 , 4 ]) plt.ylabel('some numbers' ) plt.show()
Python 默认 x 向量长度与 y 相同,且从 0 开始,因此,x = [0, 1, 2, 3]
。 pyplot 方法text()
:在任意位置添加文本xlabel()
:将文本添加到 x 轴ylabel()
:将文本添加到 y 轴title()
:将标题添加到图中savefig()
:将图形保存到文件中legend()
:在图上显示图例1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import matplotlib.pyplot as plty1 = [] y2 = [] x = range (-100 , 100 , 10 ) for i in x: y1.append(i**2 ) for i in x: y2.append(-(i**2 )) plt.plot(x, y1) plt.plot(x, y2) plt.xlabel("x" ) plt.ylabel("y" ) plt.ylim(-2000 , 2000 ) plt.axhline(0 ) plt.axvline(0 ) plt.savefig("quad.png" ) plt.show()
折线图 简单折线图1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import matplotlib.pyplot as pltx = [1 , 2 , 3 ] y = [2 , 4 , 1 ] plt.plot(x, y, color="g" ) plt.xlabel("x - axis" ) plt.ylabel("y - axis" ) plt.title("My first graph!" ) plt.show()
有两条线的折线图1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import matplotlib.pyplot as pltx1 = [1 , 2 , 3 ] y1 = [2 , 4 , 1 ] plt.plot(x1, y1, label="line 1" ,color="g" ) x2 = [1 , 2 , 3 ] y2 = [4 , 1 , 3 ] plt.plot(x2, y2, label="line 2" ,color="r" ) plt.xlabel('x - axis' ) plt.ylabel('y - axis' ) plt.title('Two lines on same graph!' ) plt.legend() plt.show()
定制折线图1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import matplotlib.pyplot as pltx = [1 , 2 , 3 , 4 , 5 , 6 ] y = [2 , 4 , 1 , 5 , 2 , 6 ] plt.plot(x, y, color='green' , linestyle='dashed' , linewidth=3 , marker='o' , markerfacecolor='blue' , markersize=12 ) plt.ylim(1 , 8 ) plt.xlim(1 , 8 ) plt.xlabel('x - axis' ) plt.ylabel('y - axis' ) plt.title('Some cool customizations!' ) plt.show()
线条标记符号 标记 描述 "." point "," pixel "o" circle "v" triangle_down "^" triangle_up "<" triangle_left ">" triangle_right "1" tri_down "2" tri_up "3" tri_left "4" tri_right "8" octagon "s" square "p" pentagon "P" plus (filled) "*" star "h" hexagon1 "H" hexagon2 "+" plus "x" x "X" x (filled) "D" diamond "d" thin_diamond "|" vline "_" hline 0 (TICKLEFT) tickleft 1 (TICKRIGHT) tickright 2 (TICKUP) tickup 3 (TICKDOWN) tickdown 4 (CARETLEFT) caretleft 5 (CARETRIGHT) caretright 6 (CARETUP) caretup 7 (CARETDOWN) caretdown 8 (CARETLEFTBASE) caretleft (centered at base) 9 (CARETRIGHTBASE) caretright (centered at base) 10 (CARETUPBASE) caretup (centered at base) 11 (CARETDOWNBASE) caretdown (centered at base)
颜色符号 颜色 k
黑色 b
蓝色 c
青色 g
绿色 m
洋红 r
红色 y
黄色 gray
或 grey
灰色 lightgray
或 lightgrey
浅灰色
柱形图 简单柱形图1 2 3 4 5 6 7 8 import matplotlib.pyplot as pltvalues = [5 , 6 , 3 , 7 , 2 ] names = ["A" , "B" , "C" , "D" , "E" ] plt.bar(names, values, color="green" ) plt.show()
names 表示 x 的坐标值,默认位置是每个柱状图所在的中点位置。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import matplotlib.pyplot as pltheight = [10 , 24 , 36 , 40 , 5 ] names = ["one" , "two" , "three" , "four" , "five" ] c1 = ["red" , "green" ] c2 = ["b" , "g" ] plt.bar(names, height, width=0.8 , color=c1) plt.xlabel("x - axis" ) plt.ylabel("y - axis" ) plt.title("My bar chart!" ) plt.show()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import matplotlib.pyplot as pltimport numpy as npheight = [10 , 24 , 36 , 40 , 5 ] names = ["one" , "two" , "three" , "four" , "five" ] c1 = ["red" , "green" ] c2 = ["b" , "g" ] index = np.arange(len (names)) plt.bar(index, height, width=0.8 , color=c1) plt.xlabel("x - axis" ) plt.xticks(index, names) plt.ylabel("y - axis" ) plt.title("My bar chart!" ) plt.show()
xticks(locs, [labels], **kwargs)
,其中 locs
用于设置 X 轴刻度间隔,labels
用于设置每个间隔的显示标签。 柱形图(堆积柱形图)1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import numpy as npimport matplotlib.pyplot as pltcountries = ["USA" , "India" , "China" , "Russia" , "Germany" ] bronzes = np.array([38 , 17 , 26 , 19 , 15 ]) silvers = np.array([37 , 23 , 18 , 18 , 10 ]) golds = np.array([46 , 27 , 26 , 19 , 17 ]) index = np.arange(len (countries)) plt.bar(index, golds, width=0.8 , label="golds" , color="gold" , bottom=silvers + bronzes) plt.bar(index, silvers, width=0.8 , label="silvers" , color="silver" , bottom=bronzes) plt.bar(index, bronzes, width=0.8 , label="bronzes" , color="#CD853F" ) plt.xticks(index, countries) plt.ylabel("Medals" ) plt.xlabel("Countries" ) plt.legend(loc="upper right" ) plt.title("2019 Olympics Top Scorers" ) plt.show()
柱形图(簇状柱形图)1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import numpy as npimport matplotlib.pyplot as pltdata = [ [30 , 25 , 50 , 20 ], [40 , 23 , 51 , 17 ], [35 , 22 , 45 , 19 ], ] X = np.arange(4 ) plt.bar(X + 0.00 , data[0 ], color="b" , width=0.25 , label="2014" ) plt.bar(X + 0.25 , data[1 ], color="g" , width=0.25 , label="2016" ) plt.bar(X + 0.50 , data[2 ], color="r" , width=0.25 , label="2022" ) plt.xticks(X + 0.25 , ["China" , "US" , "UK" , "Russia" ]) plt.ylabel("Medals" ) plt.xlabel("Countries" ) plt.title("Olympics Top Scorers" ) plt.legend() plt.legend(loc="upper right" ) plt.show()
图例 loc 参数的表示方法图例 loc 参数的表示方法,分为字符串和整数两种: 位置 字符串表示 整数数字表示 自适应 Best 0 右上方 upper right 1 左上方 upper left 2 左下 lower left 3 右下 lower right 4 右侧 right 5 居中靠左 center left 6 居中靠右 center right 7 底部居中 lower center 8 上部居中 upper center 9 中部 center 10
条形图我们还可以将柱形图水平翻转得到条形图,如下所示:1 2 3 4 5 6 7 8 9 import matplotlib.pyplot as pltvalues = [5 , 6 , 3 , 7 , 2 ] names = ["A" , "B" , "C" , "D" , "E" ] plt.barh(names, values, color="yellowgreen" ) plt.show()
直方图1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import matplotlib.pyplot as pltages = [2 , 5 , 70 , 40 , 30 , 45 , 50 , 45 , 43 , 40 , 44 , 60 , 7 , 13 , 57 , 18 , 90 , 77 , 32 , 21 , 20 , 40 ] range = (0 , 100 )bins = 10 plt.hist(ages, bins, range , color="green" , histtype="bar" , rwidth=0.98 ) plt.xlabel("age" ) plt.ylabel("No. of people" ) plt.title("My histogram" ) plt.show()
1 2 3 4 5 6 7 8 import matplotlib.pyplot as pltx = [2 , 1 , 6 , 4 , 2 , 4 , 8 , 9 , 4 , 2 , 4 , 10 , 6 , 4 , 5 , 7 , 7 , 3 , 2 , 7 , 5 , 3 , 5 , 9 , 2 , 1 ] plt.hist(x, bins=10 , color="blue" , alpha=0.5 ) plt.show()
代码段添加了两个新参数: Bins : 是一个直方图的特定参数,允许用户自定义所需的箱数。Alpha : 显示数据点的透明度程度。 散点图1 2 3 4 5 6 7 8 import matplotlib.pyplot as pltx_values = [0 , 1 , 2 , 3 , 4 , 5 ] y_values = [0 , 1 , 4 , 9 , 16 , 25 ] plt.scatter(x_values, y_values, s=30 , color="blue" ) plt.show()
注意:绘图代码由plt.bar()
改为了plt.scatter()
。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import matplotlib.pyplot as pltx = [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ] y = [2 , 4 , 5 , 7 , 6 , 8 , 9 , 11 , 12 , 12 ] plt.scatter(x, y, label="stars" , color="green" , marker="*" , s=30 ) plt.xlabel("x - axis" ) plt.ylabel("y - axis" ) plt.title("My scatter plot!" ) plt.legend() plt.show()
饼图1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import matplotlib.pyplot as pltactivities = ["eat" , "sleep" , "work" , "play" ] slices = [3 , 7 , 8 , 6 ] colors = ["r" , "y" , "g" , "b" ] plt.pie(slices, labels=activities, colors=colors, startangle=90 , shadow=True , explode=(0 , 0 , 0.1 , 0 ), radius=1.2 , autopct="%1.1f%%" ) plt.legend() plt.show()
autopct 用于使用 Python 字符串格式显示百分比值。
盒图盒图 能能通过一组数据的最大值、最小值、中位数、及上下四分位数显示数据的分布 。1 2 3 4 5 6 7 8 9 10 11 12 13 14 import numpy as npimport matplotlib.pyplot as pltnp.random.seed(10 ) collectn_1 = np.random.normal(100 , 10 , 200 ) collectn_2 = np.random.normal(80 , 30 , 200 ) collectn_3 = np.random.normal(90 , 20 , 200 ) collectn_4 = np.random.normal(70 , 25 , 200 ) data_to_plot=[collectn_1,collectn_2,collectn_3,collectn_4] plt.boxplot(data_to_plot) index = np.arange(1 , 5 ) plt.xticks(index, ['China' , 'US' , 'UK' , 'Russia' ]) plt.show()
小提琴图小提琴图 是用来展示数据分布状态 以及概率密度 的图表。这种图表结合了箱形图和密度图的特征。小提琴图跟箱形图类似,不同之处在于小提琴图还显示数据在不同数值下的概率密度 。1 2 3 4 5 6 7 8 9 10 11 12 13 14 import numpy as npimport matplotlib.pyplot as pltnp.random.seed(10 ) collectn_1 = np.random.normal(100 , 10 , 200 ) collectn_2 = np.random.normal(80 , 30 , 200 ) collectn_3 = np.random.normal(90 , 20 , 200 ) collectn_4 = np.random.normal(70 , 25 , 200 ) data_to_plot=[collectn_1,collectn_2,collectn_3,collectn_4] plt.violinplot(data_to_plot) index = np.arange(1 , 5 ) plt.xticks(index, ['China' , 'US' , 'UK' , 'Russia' ]) plt.show()
绘制给定方程的曲线1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import matplotlib.pyplot as pltimport numpy as npx = np.arange(0 , 2 * (np.pi), 0.1 ) y = np.sin(x) plt.text(3.5 , 0.5 , "$y=sin(x), x\\in[0,2\\pi)$" ) plt.plot(x, y) plt.show()
绘制极线图plt.polar(theta, r)
theta
:每个标记所在射线与极径的夹角。r
:每个标记到原点的距离。1 2 3 4 5 6 7 8 9 10 11 12 import matplotlib.pyplot as pltimport numpy as npbarSlices = 12 theta = np.linspace(0.0 , 2 * np.pi, barSlices, endpoint=False ) r = 30 * np.random.rand(barSlices) plt.polar(theta, r, color="chartreuse" , linewidth=2 , marker="*" , mfc="b" , ms=10 ) plt.show()
在 matplotlib 中,面向对象编程的核心思想是创建图形对象 ,然后通过图形对象来调用其它的方法和属性。在这个过程中,pyplot 负责生成图形对象,并通过该对象来添加一个或多个绘图区域 (即 axes 对象)。 通过调用 pyplot 模块中 figure()
函数来实例化 figure 对象。 1 2 3 4 import matplotlib.pyplot as pltfig = plt.figure()
使用 add_axes() 添加一个子绘图区域到画布中。如下所示: 1 ax = fig.add_axes([0 ,0 ,1 ,1 ])
add_axes(left, bottom, width, height)
。四个值分别表示添加到画布矩形区域的左下角坐标 (x, y),以及宽度和高度。注意:每个数字必须介于 0 到 1 之间 。使用 add_axes()
可添加一个子绘图区域到画布(figure),产生的子绘图区域用 ax 对象表示。通过 ax 可进行图像绘制。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import matplotlib.pyplot as pltimport numpy as npimport mathx = np.arange(0 , math.pi * 2 , 0.05 ) y = np.sin(x) fig = plt.figure() ax = fig.add_axes([0 , 0 , 1 , 1 ]) ax.plot(x, y) ax.set_title("sine wave" ) ax.set_xlabel("angle" ) ax.set_ylabel("sine" ) plt.show()
figure()
函数来实例化 figure 对象的参数值,如下所示:参数 说明 figsize 指定画布的大小 (宽度,高度),单位为英寸。 dpi 指定绘图对象的分辨率,即每英寸多少个像素,默认值为 80。 facecolor 背景颜色。 edgecolor 边框颜色。 frameon 是否显示边框。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import matplotlib.pyplot as pltimport numpy as npimport mathx = np.arange(0 , math.pi * 2 , 0.05 ) y = np.sin(x) fig = plt.figure(figsize=(5 , 5 ), facecolor="green" , dpi=50 ) ax = fig.add_axes([0 , 0 , 1 , 1 ]) ax.plot(x, y) ax.set_title("sine wave" ) ax.set_xlabel("angle" ) ax.set_ylabel("sine" ) plt.show()
绘制图像之前也可不调用figure()
函数创建全局绘图区域 ,此时,plt 子库会自动创建一个默认的绘图区域 。1 2 3 4 5 6 7 8 9 10 11 12 13 import matplotlib.pyplot as pltimport numpy as npimport mathx = np.arange(0 , math.pi * 2 , 0.05 ) y = np.sin(x) plt.plot(x, y) plt.title("sine wave" ) plt.xlabel("angle" ) plt.ylabel("sine" ) plt.show()
子图 subplot(创建单个子图)**subplot(nrows, ncols, plot_number)
**用于在全局绘图区域内创建子绘 图区域,其参数表示将全局绘图区域分成nrows
行和ncols
列,并根据先行后列的计数方式在plot_number
位置生成一个坐标系。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import numpy as npimport matplotlib.pyplot as pltx = np.arange(0 , 3 * np.pi, 0.1 ) y_sin = np.sin(x) y_cos = np.cos(x) plt.subplot(2 , 1 , 1 ) plt.plot(x, y_sin) plt.title("Sine" ) plt.subplot(2 , 1 , 2 ) plt.plot(x, y_cos) plt.title("Cosine" ) plt.show()
subplots(nrows, ncols)
函数的使用方法和 subplot()
函数类似。其不同之处在于,subplots()
既创建了一个包含**若干个子图区域(由 ax 表示)**的画布,又创建了一个 figure 图形对象 ,而 subplot()
只是创建一个包含子图区域的画布。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import matplotlib.pyplot as pltimport numpy as npfig, ax = plt.subplots(2 , 2 ) x = np.arange(1 , 5 ) ax[0 ][0 ].plot(x, x * x) ax[0 ][0 ].set_title("square" ) ax[0 ][1 ].plot(x, np.sqrt(x)) ax[0 ][1 ].set_title("square root" ) ax[1 ][0 ].plot(x, np.exp(x)) ax[1 ][0 ].set_title("exp" ) ax[1 ][1 ].plot(x, np.log10(x)) ax[1 ][1 ].set_title("log" ) plt.show()
subplots(nrows, ncols)
的另外一个例子。subplots()
创建的若干个子图区域由 ax 表示 。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import numpy as npimport matplotlib.pyplot as pltx = np.arange(0 , 100 ) fig,axes=plt.subplots(2 ,2 ) ax1=axes[0 ,0 ] ax2=axes[0 ,1 ] ax3=axes[1 ,0 ] ax4=axes[1 ,1 ] ax1.plot(x, x) ax2.plot(x, -x) ax3.plot(x, x ** 2 ) ax3.grid(color='r' , linestyle='--' , linewidth=1 ,alpha=0.3 ) ax4.plot(x, np.log(x)) plt.show()
创建多个子图(面向对象的 API)add_subplot
与 add_axes
都是面向 figure 对象 的创建子图的 API。注意:pyplot 的 API 中没有此命令。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import numpy as npimport matplotlib.pyplot as pltx = np.arange(0 , 100 ) fig=plt.figure() ax1=fig.add_subplot(2 ,2 ,1 ) ax1.plot(x, x) ax3=fig.add_subplot(2 ,2 ,3 ) ax3.plot(x, x ** 2 ) ax3.grid(color='r' , linestyle='--' , linewidth=1 ,alpha=0.3 ) ax4=fig.add_subplot(2 ,2 ,4 ) ax4.plot(x, np.log(x)) plt.show()
add_subplot
与subplot
的区别 subplot
方法属于** API 绘图**,而add_subplot
方法为面向对象绘图 使用subplot
方法自动生产画布与轴域 ,而add_subplot
方法需要先添加画布 figure,再在画布上添加轴域 ,add_subplot
返回的即为子图的轴域 当绘制的子图之间出现遮挡,subplot
方法会绘制代码位置靠后的图形,而add_subplot
则会绘制所有图形,只是出现遮挡 。 add_subplot
方法:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import numpy as npimport matplotlib.pyplot as pltx = np.arange(0 , 100 ) fig = plt.figure() ax1 = fig.add_subplot(2 , 2 , 1 ) ax1.plot(x, x) ax3 = fig.add_subplot(2 , 2 , 3 ) ax3.plot(x, x**2 ) ax3.grid(color="r" , linestyle="--" , linewidth=1 , alpha=0.3 ) ax4 = fig.add_subplot(2 , 2 , 4 ) ax4.plot(x, np.log(x)) plt.show()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import numpy as npimport matplotlib.pyplot as pltx = np.arange(0 , 3 * np.pi, 0.1 ) y_sin = np.sin(x) y_cos = np.cos(x) plt.subplot(2 , 1 , 1 ) plt.plot(x, y_sin) plt.title("Sine" ) plt.subplot(2 , 1 , 2 ) plt.plot(x, y_cos) plt.title("Cosine" ) plt.show()
add_axes
为新增子区域,该区域可以座落在 figure 内任意位置,且该区域可任意设置大小 。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import numpy as npimport matplotlib.pyplot as pltfig = plt.figure() x = [1 , 2 , 3 , 4 , 5 , 6 , 7 ] y = [1 , 3 , 4 , 2 , 5 , 8 , 6 ] left, bottom, width, height = 0.1 , 0.1 , 0.8 , 0.8 ax1 = fig.add_axes([left, bottom, width, height]) ax1.plot(x, y, 'r' ) ax1.set_title('area1' ) left, bottom, width, height = 0.2 , 0.6 , 0.25 , 0.25 ax2 = fig.add_axes([left, bottom, width, height]) ax2.plot(x,y, 'b' ) ax2.set_title('area2' ) plt.show()
双轴图在一些应用场景中,有时需要绘制两个 x 轴或两个 y 轴 ,这样可以更直观 地显现图像,从而获取更有效的数据。 matplotlib 提供的 twinx()
和 twiny()
函数,除了可以实现绘制双 轴的功能外,还可以使用不同的单位来绘制曲线 ,比如一个轴绘制对数函数,另外一个轴绘制指数函数。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import matplotlib.pyplot as pltimport numpy as npfig = 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=2 ) plt.show()
移动坐标轴位置有时候需要移动坐标到某些位置,这样看曲线更加方便,比如像下图: matplotlib 中一个图默认是有四个坐标轴线,简称为 spines。这四个轴通过 top、bottom、left、right 来访问。要想实现前面的图那样显示坐标轴,主要要解决两个问题,第一个问题,就是要隐藏上面和右边两条没有用到的坐标轴;第二个问题是移动左边和下面的坐标轴的位置。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import matplotlib.pyplot as pltimport numpy as npfig = plt.figure() a1 = fig.add_axes([0 ,0 ,1 ,1 ]) x = np.arange(-10 ,10 ,0.1 ) a1.plot(x, x**2 , color='orange' , linewidth=3 ) a1.plot(x, 0.7 *x, 'b--' ) a1.set_xlabel('x axis' ) a1.set_ylabel('y axis' ) a1.spines['right' ].set_visible(False ) a1.spines['top' ].set_visible(False ) a1.set_ylim(-20 , 80 ) a1.set_xlim(-7.5 , 7.5 ) a1.spines['left' ].set_position(('data' , 0 )) a1.spines['bottom' ].set_position(('data' , 0 )) plt.show()
matplotlib grid() 设置网格格式matplotlib axes 对象提供的 grid()
方法可以开启或者关闭画布中的网格。除此之外,grid()
函数还可以设置网格的颜色、线型以及线宽等属性。grid()
的函数使用格式如下: 1 grid(color='b' , ls = '-.' , lw = 0.25 )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import matplotlib.pyplot as pltimport numpy as npfig, axes = plt.subplots(1 , 3 , figsize=(12 , 4 )) x = np.arange(1 , 11 ) axes[0 ].plot(x, x**3 , "g" , lw=2 ) axes[0 ].grid(True ) axes[0 ].set_title("default grid" ) axes[1 ].plot(x, np.exp(x), "r" ) axes[1 ].grid(color="b" , ls="-." , lw=0.25 ) axes[1 ].set_title("custom grid" ) axes[2 ].plot(x, x) axes[2 ].set_title("no grid" ) fig.tight_layout() plt.show()
注意:fig.tight_layout()
使得子图横纵坐标更加紧凑,主要用于自动调整图区的大小以及间距,使所有的绘图及其标题、坐标轴标签等都可以不重叠的完整显示在画布上。 刻度和刻度标签刻度指的是轴上数据点的标记,matplotlib 能够自动的在 x 、y 轴上绘制出刻度,但是在某些情况下,刻度标签或刻度也需要满足特定的要求。注意:通过轴对象设置刻度时需要分别通过set_xticklabels()
和 set_yticklabels()
函数设置与刻度线相对应的刻度标签。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import matplotlib.pyplot as pltimport numpy as npimport mathx = np.arange(0 , math.pi * 2 , 0.05 ) fig = plt.figure() ax = fig.add_axes([0.1 , 0.1 , 0.8 , 0.8 ]) y = np.sin(x) ax.plot(x, y) ax.set_xlabel("angle" ) ax.set_title("sine" ) ax.set_xticks([0 , 2 , 5 , 6 ]) ax.set_xticklabels(["zero" , "two" , "five" , "six" ]) ax.set_yticks([-1 , 0 , 1 ]) plt.show()
matplotlib.ticker.AutoMinorLocator(n)
类用于根据主要刻度的位置动态设置次要刻度 的位置。主刻度线需要与线性刻度均匀地间隔开。n 表示主要刻度之间的时间间隔的细分数量。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import matplotlib.pyplot as pltimport numpy as npimport mathfrom matplotlib.ticker import AutoMinorLocatorx = np.arange(0 , math.pi*2 , 0.05 ) fig = plt.figure() ax = fig.add_axes([0.1 , 0.1 , 0.8 , 0.8 ]) y = np.sin(x) ax.plot(x, y) ax.set_xlabel('angle' ) ax.set_title('sine' ) ax.set_xticks([0 ,2 ,4 ,6 ]) ax.set_xticklabels(['zero' ,'two' ,'four' ,'six' ]) minor_locator = AutoMinorLocator(5 ) ax.xaxis.set_minor_locator(minor_locator) ax.set_yticks([-1 ,0 ,1 ]) plt.show()
matplotlib 数学表达式matplotlib 中的数学公式都可以使用 Text Markup(文本标记语言)显现出来,具体的使用方法是将文本标记符放在一对、$内。这样,matplotlib 会使用其内置的 Latex 引擎绘制数学公式。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import numpy as npimport matplotlib.pyplot as pltt = np.arange(0.0 , 2.0 , 0.01 ) s = np.sin(2 *np.pi*t) plt.plot(t,s) plt.title(r'$\alpha_i> \beta_i$' , fontsize=20 ) plt.text(0.45 , 0.6 , r'$\mathrm{sin}(2 \pi t)$' , fontsize = 20 ) plt.text(0.1 , -0.5 , r'$\sqrt{2}$' , fontsize=10 ) plt.xlabel('time (s)' ) plt.ylabel('volts (mV)' ) plt.show()
显示中文字体为了正确显示中文字体,请用以下代码更改默认设置,其中'SimHei'
表示黑体字。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import matplotlib.pyplot as pltplt.rcParams["font.sans-serif" ] = ["SimHei" ] plt.rcParams["axes.unicode_minus" ] = False x = np.linspace(0 , 4 * np.pi) y = np.sin(x) plt.title("sin 曲线" ) plt.plot(x, y, "g-" , label="$sin(x)$" ) plt.show()
matplotlib 绘制文本matplotlib 可以通过下表中的方法可以绘制出相应的内容。与此同时,matplotlib 也支持绘制 Latex 包含的数学符号。 参数 说明 text 在绘图区域的任意位置添加文本。 annotate 在绘图区域的任意位置添加带有可选箭头的注释。 xlabel 在绘图区域的 x 轴上添加标签。 ylabel 在绘图区域的 y 轴上添加标签。 title 为绘图区域添加标题。 figtext 在画布的任意位置添加文本。 suptitle 为画布中添加标题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import matplotlib.pyplot as pltplt.rcParams["font.sans-serif" ]=["SimHei" ] plt.rcParams["axes.unicode_minus" ]=False plt.title('axes title' ) plt.xlabel('xlabel' ) plt.ylabel('ylabel' ) plt.text(3 , 8 , 'C 语言中网网,编程爱好者都喜欢的网站' , style='italic' ,bbox = {'facecolor' : 'yellow' },fontsize=15 ) plt.text(2 , 6 , r'an equation: $E = mc^2$' , fontsize = 15 ) plt.text(4 , 0.05 , '网址:c.biancheng.net' ,verticalalignment = 'bottom' , color = 'green' , fontsize = 15 ) plt.plot([2 ], [1 ], 'o' ) plt.annotate('C 语言中文网' , xy = (2 , 1 ), xytext = (3 , 4 ),arrowprops = dict (facecolor = 'blue' , shrink = 0.1 )) plt.xlim(0 , 10 ) plt.ylim(0 , 10 ) plt.show()
添加数据标签1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import matplotlib.pyplot as pltx = [1 , 2 , 3 , 4 , 5 , 6 ] y = [2 , 4 , 1 , 5 , 2 , 6 ] plt.plot(x, y, color="green" , linestyle="dashed" , linewidth=1 , marker="o" , markerfacecolor="blue" , markersize=3 ) plt.ylim(1 , 8 ) plt.xlim(1 , 8 ) plt.xlabel("x - axis" ) plt.ylabel("y - axis" ) plt.title("Some cool customizations!" ) for a, b in zip (x, y): plt.text(a, b + 0.1 , "%d" % b, ha="center" , va="bottom" , fontsize=12 ) plt.show()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import matplotlib.pyplot as pltimport numpy as npheight = [10 , 24 , 36 , 40 , 5 ] names = ["one" , "two" , "three" , "four" , "five" ] c1 = ["red" , "green" ] c2 = ["b" , "g" ] index = np.arange(len (names)) plt.bar(index, height, width=0.8 , color=c1) plt.xlabel("x - axis" ) plt.xticks(index, names) plt.ylabel("y - axis" ) plt.title("My bar chart!" ) for a, b in zip (index, height): plt.text(a, b, "%d" % b, ha="center" , va="bottom" , fontsize=12 ) plt.show()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import matplotlib.pyplot as pltimport numpy as npheight = [10 , 24 , 36 , 40 , 5 ] names = ["one" , "two" , "three" , "four" , "five" ] c1 = ["red" , "green" ] c2 = ["b" , "g" ] index = np.arange(len (names)) bar = plt.bar(index, height, width=0.8 , color=c1) plt.xlabel("x - axis" ) plt.xticks(index, names) plt.ylabel("y - axis" ) plt.title("My bar chart!" ) plt.bar_label(bar, fmt="%d" ) plt.show()
注意 :bar_label
的使用要求 matplotlib 版本大于等于 3.4.1,如果版本较低,是无法进行该操作的。 多边形颜色填充图表又需要使用不同的颜色来区分数据,比如数据重叠区,比如数据交叉区。 每个简单的多边形可以使用 x 坐标和 y 坐标构造,只要把这些点连接一起,再把里面的空间进行指定的颜色填充。 ax.fill(x, y)
# 使用默认的颜色填充一个多边形ax.fill(x, y, "b")
# 使用蓝色填充一个多边形ax.fill(x, y, x2, y2)
# 使用默认颜色填充两个多边形ax.fill(x, y, "b", x2, y2, "r")
# 一个蓝色,一个红色 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import numpy as npimport matplotlib.pyplot as pltfig, ax = plt.subplots() ax.grid(False ) ax.set_xlim(0 , 100 ) ax.set_ylim(0 , 100 ) x = [10 , 20 , 30 ] y = [20 , 80 , 20 ] ax.fill(x, y, color="b" ) x = [40 , 50 , 50 , 40 ] y = [20 , 20 , 40 , 40 ] ax.fill(x, y, color="r" ) plt.show()
有时候需要进行不规则图形的填充,或者两条曲线相交的部分进行填充,就需要使用函数host.fill_between()
。 matplotlib.pyplot.fill_between(x, y1, y2, where=None, interpolate=False, step=None, *, data=None, **kwargs)
此函数用来填充两条水平曲线之间的区域,区域在点(x, y1)
和(x, y2)
之间,如果还想有条件地选择区域,可以采用where
参数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import numpy as npimport matplotlib.pyplot as pltfig, host = plt.subplots() host.set_xlim(0 , 2 *np.pi) host.set_ylim(-2 , 2 ) x = np.linspace(0 , 2 *np.pi, 100 ) y = np.sin(x) host.fill_between(x,y, 0 , color = 'r' ) host.plot(x, y, color = 'b' , alpha = 0.8 ) host.plot([0 , 2 *np.pi], [0 , 0 ], color = 'b' , alpha = 0.8 ) plt.show()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import numpy as npimport matplotlib.pyplot as pltfig, ax = plt.subplots() ax.set_xlim(0 , 2 * np.pi) ax.set_ylim(-2 , 2 ) x = np.linspace(0 , 2 * np.pi, 100 ) y = np.sin(x) ax.fill_between(x, y, 0 , where=(x > np.pi) & (y < -0.5 ), color="r" ) ax.plot(x, y, color="b" , alpha=0.8 ) ax.plot([0 , 2 * np.pi], [0 , 0 ], color="b" , alpha=0.8 ) plt.show()
3D 绘图最初开发的 matplotlib,仅支持绘制 2D 图形,后来随着版本的不断更新,matplotlib 在二维绘图的基础上,构建了一部分较为实用的 3D 绘图程序包,比如 mpl_toolkits.mplot3d
,通过调用该程序包一些接口可以绘制 3D 散点图、3D 曲面图、3D 线框图等。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from mpl_toolkits import mplot3dimport numpy as npimport matplotlib.pyplot as pltfig = plt.figure() ax = plt.axes(projection="3d" ) z = np.linspace(0 , 1 , 100 ) x = z * np.sin(20 * z) y = z * np.cos(20 * z) ax.plot3D(x, y, z, "b" ) ax.set_title("3D line plot" ) plt.show()
通过 ax.scatter3D()
函数可以绘制 3D 散点图 ,代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from mpl_toolkits import mplot3dimport numpy as npimport matplotlib.pyplot as pltfig = plt.figure() ax = plt.axes(projection="3d" ) z = np.linspace(0 , 1 , 100 ) x = z * np.sin(20 * z) y = z * np.cos(20 * z) c = x + y ax.scatter3D(x, y, z, c=c) ax.set_title("3D line plot" ) plt.show()
ax.contour3D()
可以用来创建 3D 等高线图 ,该函数要求输入数据均采用二维网格式的矩阵坐标。同时,它可以在每个网格点(x,y)
处计算出一个 z 值。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 from mpl_toolkits import mplot3dimport numpy as npimport matplotlib.pyplot as pltdef f (x, y ): return np.sin(np.sqrt(x**2 + y**2 )) x = np.linspace(-6 , 6 , 30 ) y = np.linspace(-6 , 6 , 30 ) X, Y = np.meshgrid(x, y) Z = f(X, Y) fig = plt.figure() 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 contour" ) plt.show()
3D 线框图 同样要采用二维网格形式的数据,与绘制等高线图类似。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 from mpl_toolkits import mplot3dimport numpy as npimport matplotlib.pyplot as pltdef f (x, y ): return np.sin(np.sqrt(x**2 + y**2 )) x = np.linspace(-6 , 6 , 30 ) y = np.linspace(-6 , 6 , 30 ) X, Y = np.meshgrid(x, y) Z = f(X, Y) fig = plt.figure() ax = plt.axes(projection="3d" ) ax.plot_wireframe(X, Y, Z, color="black" ) ax.set_title("wireframe" ) plt.show()
3D 曲面图 表示一个指定的因变量 y 与两个自变量 x 和 z 之间的函数关系。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 from mpl_toolkits import mplot3dimport numpy as npimport matplotlib.pyplot as pltx = np.outer(np.linspace(-2 , 2 , 30 ), np.ones(30 )) y = x.copy().T z = np.cos(x**2 + y**2 ) fig = plt.figure() ax = plt.axes(projection="3d" ) ax.plot_surface(x, y, z, cmap="viridis" , edgecolor="none" ) ax.set_title("Surface plot" ) plt.show()
Part II. seaborn seabornseaborn 是一个基于 matplotlib 的 Python 数据可视化库。它 为创建有吸引力的图形提供了高级接口 。seaborn 提供了很多东西,你可以使用一行代码创建图形,而这在 matplotlib 需要十来行。 seaborn 可以方便地处理 DataFrame 数据。 可以通过以下代码导入: import seaborn as sns
提供了用于检查多个变量之间关系 的 API 专门支持对分类变量分析或聚合统计 支持单变量或双变量分布的可视化和比较 不同线性回归模型的构建和可视化 查看复杂数据集的整体结构 可构造多图网格 ,轻松实现复杂的可视化 导入数据集在本节中,我们将使用免费的 Iris 数据集。可以使用pandas.read_csv
方法加载该数据集。 1 2 3 4 import pandas as pdiris = pd.read_csv('iris.csv' , names=['sepal_length' , 'sepal_width' ,'petal_length' , 'petal_width' , 'class' ]) iris.head()
散点图可以使用.scatterplot
方法创建散点图,我们只需要将数据作为附加参数即可。 1 sns.scatterplot(x='sepal_length' , y='sepal_width' , data=iris)
我们还可以使用 hue
参数 按类别突出显示数据点,这要比 matplotlib 中简单得多。 1 sns.scatterplot(x="sepal_length" , y="sepal_width" , hue="class" , data=iris)
折线图要创建折线图,请使用 sns.lineplot
方法 。唯一需要的参数是数据,在例子中,数据是来自 Iris 数据集的四个列。 1 sns.lineplot(data=iris.drop(['class' ], axis=1 ))
在 pandas 中,drop()
函数用于删除行。axis=1
告诉 Python 在列而不是行上进行删除。 直方图在 seaborn 中可以使用sns.distplot
方法创建直方图。我们需要将要绘制的列传递给它,seaborn 将自动计算每个数值范围内值的数量。我们还可以将箱子的数量传递给它。 1 2 wine_reviews = pd.read_csv("winemag-data-130k-v2.csv" ) sns.distplot(wine_reviews["points" ], bins=10 , kde=False )
winemag-data-130k-v2.csv 数据集包含从 winemag.com 在 2017 年 6 月 15 日发布的葡萄酒评论数据。kde 用于决定是否绘制高斯核密度估计。1 sns.distplot(wine_reviews['points' ], bins=10 , kde=True )
柱形图在 seaborn 中,可以使用sns.countplot
方法创建柱形图以显示每个类别中观测值的数量。 1 sns.countplot(x="points" , data=wine_reviews, order=sorted (wine_reviews["points" ].unique()), palette=sns.color_palette("husl" , 20 ))
盒图盒须图主要包括六个统计指标:lower limit (下限), first quartile (第一四分位数), median (中位数), third quartile (第三四分位数), upper limit (上限) and outliers (异常值). 可以使用 sns.boxplot
方法创建盒须图。注意,创建盒须图需要传递 x 和 y 两个列的值。 1 2 df = wine_reviews[(wine_reviews['points' ]>=95 ) & (wine_reviews['price' ]<1000 )] sns.boxplot('points' , 'price' , data=df)
密度图密度图是数据的图形表示,其中矩阵中包含的各个值表示为颜色 。密度图非常适合探索数据集中特征的相关性 。 要获取数据集中特征的相关性,我们可以调用<dataset>.corr() ,这是 pandas 库 dataframe 方法,其将给出各列的相关矩阵 。 我们现在可以使用 matplotlib 或 seaborn 来创建密度图。 matplotlib1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import pandas as pdimport numpy as npimport matplotlib.pyplot as pltiris = pd.read_csv("iris.csv" , names=["sepal_length" , "sepal_width" , "petal_length" , "petal_width" , "class" ]) corr = iris.drop(["class" ], axis=1 ).corr() fig, ax = plt.subplots() im = ax.imshow(corr.values) ax.set_xticks(np.arange(len (corr.columns))) ax.set_yticks(np.arange(len (corr.columns))) ax.set_xticklabels(corr.columns) ax.set_yticklabels(corr.columns) plt.setp(ax.get_xticklabels(), rotation=45 , ha="right" , rotation_mode="anchor" ) plt.show()
要向密度图添加注释,我们需要添加两个 for 循环: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 corr = iris.drop(["class" ], axis=1 ).corr() fig, ax = plt.subplots() im = ax.imshow(corr.values) ax.set_xticks(np.arange(len (corr.columns))) ax.set_yticks(np.arange(len (corr.columns))) ax.set_xticklabels(corr.columns) ax.set_yticklabels(corr.columns) plt.setp(ax.get_xticklabels(), rotation=45 , ha="right" , rotation_mode="anchor" ) columns = [0 , 1 , 2 , 3 ] for i in columns: for j in columns: text = ax.text(j, i, np.around(corr.iloc[i, j], decimals=2 ), ha="center" , va="center" , color="black" )
seabornseaborn 使得创建密度图和添加注释变得更加容易: 1 sns.heatmap(iris.drop(["class" ], axis=1 ).corr(), annot=True )
分面(Faceting)分面是将数据变量分解成多个子图,并将这些子图组合成单个图形的行为 。如果想快速浏览数据集,分面非常有用。 要在 seaborn 中使用分面,可以使用 FaceGrid 。 首先,需要定义 FaceGrid,并将数据以及行或列传递给它,这将用于拆分数据。 然后,需要在 FaceGrid 对象上调用** map 函数**,并定义要使用的绘图类型以及要绘制的列。 1 2 g = sns.FacetGrid(iris, col="class" ) g = g.map (sns.kdeplot, "sepal_length" )
FacetGrid
将数据集映射到多个轴上,这些轴排列在与数据集中变量级别相对应的行或列网格中。FacetGrid.map
函数将绘图函数应用于每个方面的数据子集。 Pairplot(联合分布图)seaborns 的 pairplot 和 pandas 的 scatter_matrix 能够在数据集中绘制成对变量之间关系的网格。 1 2 3 4 from pandas.plotting import scatter_matrixfig, ax = plt.subplots(figsize=(12 ,12 )) scatter_matrix(iris, alpha=1 , ax=ax)
可以看到,联合分布图总是需要两个变量进行绘制。图的对角线用直方图填充,其他图是散点图。 Part III. 本章总结在本章中,我们学习了如何使用 Matplotlib 和 Seaborn 进行数据可视化。这两个库在 Python 数据科学领域中非常重要,提供了丰富的图形绘制功能。以下是对本章内容的总结:
Matplotlib 基础绘图安装与导入 :使用 pip install matplotlib
安装,import matplotlib.pyplot as plt
导入。基本用法 :通过 plt.plot()
、plt.show()
等函数创建和显示图形。常用图形 :折线图、柱形图、条形图、直方图、散点图、饼图、盒图、小提琴图等。 高级绘图子图与布局 :使用 subplot()
和 add_subplot()
创建多个子图。双轴图 :通过 twinx()
和 twiny()
实现双轴图。3D 绘图 :使用 mpl_toolkits.mplot3d
创建 3D 图形,如线图、散点图、等高线图等。 自定义与美化文本与注释 :通过 text()
和 annotate()
添加文本和注释。网格与刻度 :使用 grid()
添加网格,set_xticks()
和 set_yticks()
设置刻度。颜色与填充 :fill_between()
实现区域填充,设置颜色和透明度。 Seaborn 基础绘图导入与数据集 :通过 import seaborn as sns
导入,方便处理 DataFrame 数据。常用图形 :散点图、折线图、直方图、柱形图、盒图、密度图等。 高级绘图分面与网格 :使用 FacetGrid
实现数据按类别分面的可视化。联合分布图 :pairplot()
绘制成对变量之间关系的网格。 3.2.3 自定义与美化颜色与风格 :Seaborn 提供多种配色方案和风格选项,便于创建美观的图形。注释与标签 :通过参数如 hue
、annot
等实现更丰富的图形标注。 总结Matplotlib 和 Seaborn 各有优势:
Matplotlib :更底层,灵活性高,适合需要精细控制的场景。Seaborn :基于 Matplotlib,提供更高级的接口,适合快速绘制美观图形。通过本章的学习,我们可以更好地利用这两个库进行数据分析和可视化,提升数据洞察力。希望大家在实践中多多练习,熟练掌握这些工具的使用。