作者 |Rizky Maulana Nurhidayat
编译 |VK
起源 |Towards Datas Science
数据可视化用于以更间接的示意形式显示数据,并且更易于了解。它能够用柱状图、散点图、折线图、饼图等模式造成。许多人依然应用 Matplotlib 作为后端模块来可视化他们的图形。在这个故事中,我将给你一些技巧,应用 Matplotlib 创立一个优良图表的 5 个弱小技巧。
1. 应用 Latex 字体
默认状况下,咱们能够应用 Matplotlib 提供的一些不错的字体。然而,有些符号不够好,不能由 Matplotlib 创立。例如,符号 phi(φ),如图 1 所示。
正如你在 y -label 中看到的,它依然是 phi(φ)的符号,然而对于某些人来说,它还不足以作为绘图标签。为了使它更丑陋,你能够应用 Latex 字体。如何应用它?答案就在这里。
plt.rcParams['text.usetex'] = True
plt.rcParams['font.size'] = 18
你能够在 python 代码的结尾增加下面的代码。第 1 行定义绘图中应用的 LaTeX 字体。你还须要定义大于默认大小的字体大小。如果你不换,我想它会给你一个小标签。我选了 18。利用上述代码后的后果如图 2 所示。
你须要在符号的结尾和结尾写上双美元符号,像这样($…$)
plt.xlabel('x')
plt.ylabel('$\phi$ (phi)')
如果你有一些谬误或没有装置应用 LaTeX 字体所需的库,则须要通过在 Jupyter notebook 中运行以下代码来装置这些库。
!apt install texlive-fonts-recommended texlive-fonts-extra cm-super dvipng
如果你想通过终端装置,能够输出
apt install texlive-fonts-recommended texlive-fonts-extra cm-super dvipng
当然,你能够应用一些不同的字体系列,如 serif、sans-serif(下面的示例)等。要更改字体系列,能够应用以下代码。
plt.rcParams['font.family'] = "serif"
如果你将下面的代码增加到代码中,它将给你一个图,如图 3 所示。
你能了解图 3 和图 2 之间的区别吗?是的,如果你仔细分析,区别在于字体的尾部。后一个图形应用 serif,而前者应用 sans-serif。简而言之,serif 示意尾,sans 示意没有。如果你想理解更多无关字体系列或字体的信息,我倡议你应用此链接。
https://en.wikipedia.org/wiki…
你还能够应用 Jupyter themes 库设置字体系列 / 字体。我曾经做了应用它的教程。只需单击以下链接。Jupyter 主题也能够扭转你的 Jupyter 主题,例如暗模式主题:https://medium.com/@rizman18/…
咱们心愿插入简单文本,如图 4 的题目所示。
如果你想创立图 4,能够应用这个残缺的代码
# 导入库
import numpy as np
import matplotlib.pyplot as plt
# 调整 matplotlib 参数
plt.rcParams.update(plt.rcParamsDefault)
plt.rcParams['text.usetex'] = True
plt.rcParams['font.size'] = 18
plt.rcParams['font.family'] = "serif"
# 创立模仿数据
r = 15
theta = 5
rw = 12
gamma = 0.1
err = np.arange(0., r, .1)
z = np.where(err < rw, 0, gamma * (err-rw)**2 * np.sin(np.deg2rad(theta)))
# 可视化数据
plt.scatter(err, z, s = 10)
plt.title(r'$\Sigma(x) = \gamma x^2 \sin(\theta)$', pad = 20)
plt.xlabel('x')
plt.ylabel('$\phi$')
# 保留图表
plt.savefig('latex.png', dpi = 300, pad_inches = .1, bbox_inches = 'tight')
2. 创立缩放成果
在这个技巧中,我将给你一个生成绘图的代码,如图 5 所示。
首先,你须要理解 plt.axes() 和plt.figure() 你能够在上面的链接中查看它。代码 plt.figure() 笼罩单个容器中的所有对象,包含轴、图形、文本和标签。代码plt.axes() 只蕴含特定的局部。我想,图 6 能够给你一个简略的了解。
黑盒子应用plt.figure(),红色和蓝色的盒子应用plt.axes(). 在图 6 中,有两个轴,红色和蓝色。你能够查看此链接以获取根本参考:https://medium.com/datadriven…
了解之后,你能够剖析如何创立图 5。是的,简略地说,图 5 中有两个轴。第一个轴是一个大的绘图,放大版本从 580 到 650,第二个是放大版本。上面是创立图 5 的代码。
# 创立主容器
fig = plt.figure()
# 设置随机种子
np.random.seed(100)
# 创立模仿数据
x = np.random.normal(400, 50, 10_000)
y = np.random.normal(300, 50, 10_000)
c = np.random.rand(10_000)
# 创立放大图
ax = plt.scatter(x, y, s = 5, c = c)
plt.xlim(400, 500)
plt.ylim(350, 400)
plt.xlabel('x', labelpad = 15)
plt.ylabel('y', labelpad = 15)
# 创立放大图
ax_new = fig.add_axes([0.6, 0.6, 0.2, 0.2]) # 放大图的地位与放大图的比例比拟
plt.scatter(x, y, s = 1, c = c)
# 保留图形,留好边距
plt.savefig('zoom.png', dpi = 300, bbox_inches = 'tight', pad_inches = .1)
如果你须要代码的解释,能够拜访此链接:https://medium.com/datadriven…
我还提供了另一个版本的缩放成果,你能够应用 Matplotlib。如图 7 所示。
要创立图 7,你须要在 Matplotlib 中应用 add_subblot 或其余语法(subblot)创立三个轴。为了更容易应用,我在这里加上。要创立它们,能够应用以下代码。
fig = plt.figure(figsize=(6, 5))
plt.subplots_adjust(bottom = 0., left = 0, top = 1., right = 1)
# 创立第一个轴,左上角的图用绿色的图
sub1 = fig.add_subplot(2,2,1) # 两行两列,第一单元格
# 创立第二个轴,即左上角的橙色轴
sub2 = fig.add_subplot(2,2,2) # 两行两列,第二个单元格
# 创立第三个轴,第三和第四个单元格的组合
sub3 = fig.add_subplot(2,2,(3,4)) # 两行两列,合并第三和第四单元格
代码将生成一个图,如图 8 所示。它通知咱们它将生成 2 行 2 列。轴 sub1(2,2,1)是子图(第一行,第一列)中的第一个轴。程序从左上侧到右开始。轴 sub2(2,2,2)被搁置在第一行第二列中。轴 sub3(2,2,(3,4)),是第二行第一列和第二行第二列之间的合并轴。
当然,咱们须要定义一个模仿数据,以便在绘图中可视化。在这里,我定义了线性函数和正弦函数的简略组合,如上面的代码所示。
# 应用 lambda 定义函数
stock = lambda A, amp, angle, phase: A * angle + amp * np.sin(angle + phase)
# 定义参数
theta = np.linspace(0., 2 * np.pi, 250) # x 轴
np.random.seed(100)
noise = 0.2 * np.random.random(250)
y = stock(.1, .2, theta, 1.2) + noise # y 轴
如果你将代码利用到后面的代码中,你将失去一个图,如图 9 所示。
下一步是限度第一个和第二个轴(sub1 和 sub2)的 x 轴和 y 轴,为 sub3 中的两个轴创立阻塞区域,并创立代表缩放成果的 ConnectionPatch。能够应用以下残缺的代码来实现(记住,为了简略起见,我没有应用循环)。
# 应用 lambda 定义函数
stock = lambda A, amp, angle, phase: A * angle + amp * np.sin(angle + phase)
# 定义参数
theta = np.linspace(0., 2 * np.pi, 250) # x 轴
np.random.seed(100)
noise = 0.2 * np.random.random(250)
y = stock(.1, .2, theta, 1.2) + noise # y 轴
# 创立大小为 6x5 的主容器
fig = plt.figure(figsize=(6, 5))
plt.subplots_adjust(bottom = 0., left = 0, top = 1., right = 1)
# 创立第一个轴,左上角的图用绿色的图
sub1 = fig.add_subplot(2,2,1) # 两行两列,第一单元格
sub1.plot(theta, y, color = 'green')
sub1.set_xlim(1, 2)
sub1.set_ylim(0.2, .5)
sub1.set_ylabel('y', labelpad = 15)
# 创立第二个轴,即左上角的橙色轴
sub2 = fig.add_subplot(2,2,2) # 两行两列,第二个单元格
sub2.plot(theta, y, color = 'orange')
sub2.set_xlim(5, 6)
sub2.set_ylim(.4, 1)
# 创立第三个轴,第三和第四个单元格的组合
sub3 = fig.add_subplot(2,2,(3,4)) # 两行两列,合并第三和第四单元格
sub3.plot(theta, y, color = 'darkorchid', alpha = .7)
sub3.set_xlim(0, 6.5)
sub3.set_ylim(0, 1)
sub3.set_xlabel(r'$\theta$ (rad)', labelpad = 15)
sub3.set_ylabel('y', labelpad = 15)
# 在第三个轴中创立阻塞区域
sub3.fill_between((1,2), 0, 1, facecolor='green', alpha=0.2) # 第一个轴的阻塞区域
sub3.fill_between((5,6), 0, 1, facecolor='orange', alpha=0.2) # 第二轴的阻塞区域
# 在左侧创立第一个轴的 ConnectionPatch
con1 = ConnectionPatch(xyA=(1, .2), coordsA=sub1.transData,
xyB=(1, .3), coordsB=sub3.transData, color = 'green')
# 增加到左侧
fig.add_artist(con1)
# 在右侧创立第一个轴的 ConnectionPatch
con2 = ConnectionPatch(xyA=(2, .2), coordsA=sub1.transData,
xyB=(2, .3), coordsB=sub3.transData, color = 'green')
# 增加到右侧
fig.add_artist(con2)
# 在左侧创立第二个轴的 ConnectionPatch
con3 = ConnectionPatch(xyA=(5, .4), coordsA=sub2.transData,
xyB=(5, .5), coordsB=sub3.transData, color = 'orange')
# 增加到左侧
fig.add_artist(con3)
# 在右侧创立第二个轴的 ConnectionPatch
con4 = ConnectionPatch(xyA=(6, .4), coordsA=sub2.transData,
xyB=(6, .9), coordsB=sub3.transData, color = 'orange')
# 增加到右侧
fig.add_artist(con4)
# 保留图形,留好边距
plt.savefig('zoom_effect_2.png', dpi = 300, bbox_inches = 'tight', pad_inches = .1)
代码将为你提供一个杰出的缩放效果图,如图 7 所示。
3. 创立图例
你的图中是否有许多图例要显示?如果是,则须要将它们搁置在主轴之外。
要将图例搁置在主容器之外,须要应用此代码调整地位
plt.legend(bbox_to_anchor=(1.05, 1.04)) # 图例的地位
值 1.05 和 1.04 位于朝向主容器的 x 和 y 轴坐标中。你能够扭转它。当初,把下面的代码利用到咱们的代码中,
# 应用 lambda 创立 wave 函数
wave = lambda amp, angle, phase: amp * np.sin(angle + phase)
# 设置参数值
theta = np.linspace(0., 2 * np.pi, 100)
amp = np.linspace(0, .5, 5)
phase = np.linspace(0, .5, 5)
# 创立主容器及其题目
plt.figure()
plt.title(r'Wave Function $y = \gamma \sin(\theta + \phi_0) $', pad = 15)
# 为每个放大器和阶段创立绘图
for i in range(len(amp)):
lgd1 = str(amp[i])
lgd2 = str(phase[i])
plt.plot(theta, wave(amp[i], theta, phase[i]), label = (r'$\gamma = $'+lgd1+', $\phi = $' +lgd2))
plt.xlabel(r'$\theta$ (rad)', labelpad = 15)
plt.ylabel('y', labelpad = 15)
# 调整图例
plt.legend(bbox_to_anchor=(1.05, 1.04))
# 保留图形,留好边距
plt.savefig('outbox_legend.png', dpi = 300, bbox_inches = 'tight', pad_inches = .1)
运行代码后,它将给出一个图,如图 11 所示。
如果要使图例框更丑陋,能够应用以下代码增加暗影成果。它将显示一个图,如图 12 所示。
plt.legend(bbox_to_anchor=(1.05, 1.04), shadow=True)
4. 创立间断误差图
在过来的十年里,数据可视化的格调被转移到一个洁净的绘图主题上。通过浏览国内期刊或网页上的一些新论文,咱们能够看到这种转变。最风行的办法之一是用间断的误差可视化数据,而不是应用误差条。你能够在图 13 中看到它。
图 13 是通过应用 fill_between 生成的。在 fill_between 语法中,你须要定义下限和上限,如图 14 所示。
要利用它,能够应用以下代码。
plt.fill_between(x, upper_limit, lower_limit)
参数下限和上限能够调换。这是残缺的代码。
N = 9
x = np.linspace(0, 6*np.pi, N)
mean_stock = (stock(.1, .2, x, 1.2))
np.random.seed(100)
upper_stock = mean_stock + np.random.randint(N) * 0.02
lower_stock = mean_stock - np.random.randint(N) * 0.015
plt.plot(x, mean_stock, color = 'darkorchid', label = r'$y = \gamma \sin(\theta + \phi_0)$')
plt.fill_between(x, upper_stock, lower_stock, alpha = .1, color = 'darkorchid')
plt.grid(alpha = .2)
plt.xlabel(r'$\theta$ (rad)', labelpad = 15)
plt.ylabel('y', labelpad = 15)
plt.legend()
plt.savefig('fill_between.png', dpi = 300, bbox_inches = 'tight', pad_inches = .1)
5. 调整边距
如果你剖析下面的每一行代码,plt.savefig()前面会是一个简单的参数:bbox_inches 和 pad_inches。当你在撰写一篇期刊或文章时,它们会为你提供边距。如果不包含它们,则保留后,绘图的边距将更大。图 15 展现了有 bbox_inches 和 pad_inches 以及没有它们的不同绘图。
我想你看不出图 15 中两个图之间的区别。我将尝试用不同的背景色来显示它,如图 16 所示。
同样,当你在一篇论文或一篇文章中插入你的图表时,这个技巧会帮忙你。你不须要裁剪它来节俭空间。
论断
Matplotlib 是一个多平台库,能够在许多操作系统应用。它是将数据可视化的老库之一,但它依然很弱小。因为开发人员总是依据数据可视化的趋势进行一些更新。下面提到的一些技巧就是更新的例子。
原文链接:https://towardsdatascience.co…
欢送关注磐创 AI 博客站:
http://panchuang.net/
sklearn 机器学习中文官网文档:
http://sklearn123.com/
欢送关注磐创博客资源汇总站:
http://docs.panchuang.net/