本教程旨在展示使用Matplotlib的单个可视化的开始、中间和结束。
我们将从一些原始数据开始,最后保存一个定制的可视化图形。
在此过程中,我们尝试使用Matplotlib来突出一些整洁的特性和最佳实践。
注意:本教程基于克里斯·莫菲特这篇优秀的博客文章。它被克里斯·霍德格拉夫转化为本教程。
关于面向对象的API与Pyplot的说明
Matplotlib有两个接口,第一个是面向对象(OO)接口。在本例中,我们使用axes.ax的一个实例来呈现图形实例上的可视化。
第二部分基于MATLAB,采用基于状态的接口,封装在pyplot模块中。更深入地了解pyplote界面,请参阅pyplot教程。
大多数术语都是直截了当的,但主要要记住的是:
- 图形是可能包含一个或多个绘图区域的最终图像。
- Axes表示一个单独的绘图区域(不要将"Axes"与“Axis”一词混淆,后者指的是绘图的坐标轴)。
我们调用直接从绘图区域进行绘图的方法,这给了我们更大的灵活性和更大的力量来定制我们的图像。
注意:通常情况下,尝试使用面向对象的接口而不是pyplot接口。
我们的数据
我们将使用来自于本教程的文章的数据,它包含了一些公司的销售信息。
import numpy as np
import matplotlib.pyplot as plt
data = {'Barton LLC': 109438.50,
'Frami, Hills and Schmidt': 103569.59,
'Fritsch, Russel and Anderson': 112214.71,
'Jerde-Hilpert': 112591.43,
'Keeling LLC': 100934.30,
'Koepp Ltd': 103660.54,
'Kulas Inc': 137351.96,
'Trantow-Barrows': 123381.38,
'White-Trantow': 135841.99,
'Will LLC': 104437.60}
group_data = list(data.values())
group_names = list(data.keys())
group_mean = np.mean(group_data)
开始
这些数据自然被可视化为一个条形图,每个组有一个bar。为了使用面向对象的方法来实现这一点,我们首先生成一个图形实例:图形和绘图区域。图形就像一个画布,而绘图区域是画布的一部分,我们将在其中进行一个特定的可视化。
注意:图形上可以有多个绘图区域。有关如何执行此操作的信息,请参阅Tight Layout 教程。
fig, ax = plt.subplots()
现在我们有了一个Axes实例,我们可以在上面绘图。
fig, ax = plt.subplots()
ax.barh(group_names, group_data)
输出:
<BarContainer object of 10 artists>
控制样式
Matplotlib中有许多可用的样式,以便使您能够根据需要定制可视化。如果有一个样式列表,那么我们就可以参考使用。
print(plt.style.available)
输出:
['Solarize_Light2', '_classic_test_patch', 'bmh', 'classic', 'dark_background
↪', 'fast', 'fivethirtyeight', 'ggplot', 'grayscale', 'seaborn', 'seaborn-
↪bright', 'seaborn-colorblind', 'seaborn-dark', 'seaborn-dark-palette',
↪'seaborn-darkgrid', 'seaborn-deep', 'seaborn-muted', 'seaborn-notebook',
↪'seaborn-paper', 'seaborn-pastel', 'seaborn-poster', 'seaborn-talk',
↪'seaborn-ticks', 'seaborn-white', 'seaborn-whitegrid', 'tableau-colorblind10
↪']
可以使用以下命令激活样式:
plt.style.use('fivethirtyeight')
现在,让我们重新制作上面的图形,看看它看起来是怎样的:
fig, ax = plt.subplots()
ax.barh(group_names, group_data)
plt.style.use('fivethirtyeight')
输出:
<BarContainer object of 10 artists>
样式控制许多东西,例如颜色、线宽、背景等。
定制图形
现在我们有了一个我们想要的总体外观的图形,所以让我们微调一下,这样它就可以打印了。首先,我们在x轴上旋转标签,使它们更清晰地显示出来。我们可以使用axes.Axes.get_xticklabels()方法访问这些标签:
fig, ax = plt.subplots()
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
![在这里插入图片描述](
如果我们想同时设置多个项目的属性,使用pyplot.setp() 函数很有用。这将获取Matplotlib对象的列表(或多个列表),并尝试设置每个对象的某些样式元素。
fig, ax = plt.subplots()
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
输出:
[None, None, None, None, None, None, None, None, None, None, None, None, None,
↪ None, None, None, None, None]
看上去像是把底部的一些标签剪掉了。我们可以告诉Matplotlib在我们创建的图形中自动为元素腾出空间。为此,我们设置了rcParams的autolayout值。有关用rcParams控制图形的样式、布局和其他特性的表单信息,使用样式表和rcParams可以查看Matplotlib with style sheets and rcParams。
plt.rcParams.update({'figure.autolayout': True})
fig, ax = plt.subplots()
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
输出:
[None, None, None, None, None, None, None, None, None, None, None, None, None,
↪ None, None, None, None, None]
接下来,我们将标签添加到绘图中。为了使用OO接口实现这一点,我们可以使用Artist.set()方法,设置此Axes对象的属性。
fig, ax = plt.subplots()
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',title='Company Revenue')
输出:
[(-10000.0, 140000.0), Text(0.5, 0, 'Total Revenue'), Text(0, 0.5, 'Company'),
↪ Text(0.5, 1.0, 'Company Revenue')]
我们还可以使用pyplot.subplots()函数来调整这个绘图的大小。我们也可以figsize参数来调整绘图的大小。
注意:NumPy中的索引遵循表单(行、列),而图形大小的参数kwarg则遵循表单(宽度、高度)。这在可视化方面遵循惯例,不幸的是,这与线性代数不同。
fig, ax = plt.subplots(figsize=(8, 4)) # 调整画布的大小
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',title='Company Revenue')
输出:
[(-10000.0, 140000.0), Text(0.5, 0, 'Total Revenue'), Text(0, 0.5, 'Company'),Text(0.5, 1.0, 'Company Revenue')]
For labels,we can specify custom formatting guidelines in the form of functions. Below we definea function that takes an integer as input,and returns a string as an output. When used with axis.set_major_formatter or Axis.set_minor_formatter, they will automatically create and usea ticker.FuncFormatter class.
对于标签,我们可以以函数的形式指定自定义格式指南。
下面我们定义了一个函数,它以一个整数作为输入,并返回一个字符串作为输出。当与Axis.
set_major_formatter
或 Axis.set_minor_formatter
一起使用时,它们将自动创建和使用ticker.FuncFormatter类。
对于这个函数,x参数是原始的 tick 标签,pos是 tick 位置。我们将只使用x.here,但这两个参数都是必需的。
def currency(x, pos):
"""The two args are the value and tick position"""
if x >= 1e6:
s = '${:1.1f}M'.format(x*1e-6)
else:
s = '${:1.0f}K'.format(x*1e-3)
return s
将此函数应用于绘图中的标签。要做到这一点,我们使用了axes的.xaxis属性ax.xaxis
,这允许您在绘图图上的特定轴上执行操作。
fig, ax = plt.subplots(figsize=(6, 8))
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',title='Company Revenue')
ax.xaxis.set_major_formatter(currency)
组合多个可视化
在相同的绘图区域上绘制多个绘图元素是可能的。要做到这一点,我们只需调用axes.Axes.
对象上的另一个绘图方法。
fig, ax = plt.subplots(figsize=(8, 8))
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
# 添加一条竖线,在这里我们设置函数调用中的样式
ax.axvline(group_mean, ls='--', color='r')
# 注释新公司
for group in [3, 5, 8]:
ax.text(145000, group, "New Company", fontsize=10,verticalalignment="center")
# 现在我们把标题调高,因为它有点拥挤
ax.title.set(y=1.05)
ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',title='Company Revenue')
ax.xaxis.set_major_formatter(currency)
ax.set_xticks([0, 25e3, 50e3, 75e3, 100e3, 125e3])
fig.subplots_adjust(right=.1)
plt.show()
Saving our plot
保存图形
现在我们对我们的图形的结果感到满意,我们想把它保存到磁盘中。我们可以在Matplotlib中保存许多文件格式。要查看可用选项列表,请使用:
print(fig.canvas.get_supported_filetypes())
输出:
{'eps': 'Encapsulated Postscript', 'jpg': 'Joint Photographic Experts Group',
↪'jpeg': 'Joint Photographic Experts Group', 'pdf': 'Portable Document Format
↪', 'pgf': 'PGF code for LaTeX', 'png': 'Portable Network Graphics', 'ps':
↪'Postscript', 'raw': 'Raw RGBA bitmap', 'rgba': 'Raw RGBA bitmap', 'svg':
↪'Scalable Vector Graphics', 'svgz': 'Scalable Vector Graphics', 'tif':
↪'Tagged Image File Format', 'tiff': 'Tagged Image File Format'}
然后,我们可以使用figure.Figure.savefig()来将图形保存到磁盘中。请注意,我们在下面显示了一些有用的标志:
- transparent=True 如果格式支持,则使保存的图形的背景透明。
- dpi=80 控制输出的分辨率(每平方英寸点数)
- bbox_inches=“tight” 使得图形符合界限
# 保存图形
fig.savefig('sales.png', transparent=False, dpi=80, bbox_inches="tight")