共计 6665 个字符,预计需要花费 17 分钟才能阅读完成。
Matplotlib 是 Python 中风行的数据可视化库,仅应用简略的几行代码就能够生成图表。然而默认的办法是生成的图表很简略,如果想加强数据演示的影响和清晰度,能够试试本文总结的 10 个高级技巧,这些技巧能够将可视化晋升到一个新的程度:
1、rcParams
rcParams 字典。它蕴含了用于创立图形的默认款式的所有 Matplotlib 设置。你能够间接从 matplotlib 命名空间导入它:
from matplotlib import rcParams
>>> rcParams
...
'axes.grid': False,
'axes.grid.axis': 'both',
'axes.grid.which': 'major',
'axes.labelcolor': 'black',
'axes.labelpad': 4.0,
'axes.labelsize': 'medium',
'axes.labelweight': 'normal',
'axes.linewidth': 0.8,
...
rcParams['figure.figsize'] = 8, 6
rcParams['legend.fontsize'] = "large"
rcParams['xtick.major.size'] = 4
rcParams['xtick.minor.size'] = 1
这时所有的 Matplotlib 设置,如果你想批改任何的 Matplotlib 参数,间接批改这个字典就能够了,你甚至能够将他序列化到本地,而后在其余我的项目中间接加载,这样你的每一个 Matplotlib 实例应用的都是雷同的配置了。
还能够调用 PyPlot 的 rcdefaults 函数,它会将所有参数重置成默认值。
plt.rcdefaults()
2、get_* functions
在底层,Matplotlib 是齐全面向对象的。
上图中看到的每个独自的组件都是作为一个独自的类实现的。它们都继承自基类 Matplotlib Artist。
然而类太多,并且每个类的参数都不一样这会给应用带来很大的不不便,所以 Matplotlib 定制了有许多以 get_前缀结尾的函数,能够间接创立图形中的组件。上面是一个例子:
fig, ax = plt.subplots()
>>> [func for func in dir(ax) if func.startswith("get")]
['get_adjustable',
'get_label',
'get_legend',
'get_legend_handles_labels',
'get_lines',
'get_navigate',
'get_title',
'get_transform',
'get_xmajorticklabels',
'get_xminorticklabels',
'get_xscale',
'get_xticklabels',
'get_zorder']
假如咱们想自定义一个图形的坐标:
x = np.linspace(0, 2, 100)
fig, ax = plt.subplots() # Create a figure and an axes.
l1 = ax.plot(x, x, label="linear")
l2 = ax.plot(x, x ** 2, label="quadratic")
l3 = ax.plot(x, x ** 3, label="cubic")
ax.set_title("Simple Plot")
plt.show()
这很简略,只需在 axes 对象上调用 get_xticklabels,就能够失去 Matplotlib Text 实例的列表:
>>> ax.get_xticklabels()
[Text(0, 0, 'Ideal'),
Text(1, 0, 'Premium'),
Text(2, 0, 'Very Good'),
Text(3, 0, 'Good'),
Text(4, 0, 'Fair')]
还能够应用 get_xticklines 调整刻度线,或者应用 get_xticks 调整刻度的地位。
曾经取得了对象,上面就能够进行调整了
3、get / setp
调用 plt.getp 函数,能够查看它以后具备的参数。例如,假如咱们想要款式化上面图的 l2:
x = np.linspace(0, 2, 100)
fig, ax = plt.subplots() # Create a figure and an axes.
l1 = ax.plot(x, x, label="linear")
l2 = ax.plot(x, x ** 2, label="quadratic")
l3 = ax.plot(x, x ** 3, label="cubic")
ax.set_title("Simple Plot")
plt.show()
这个办法返回了图表的所有属性
>>> plt.getp(l2)
...
drawstyle or ds = default
figure = Figure(640x480)
linestyle or ls = -
linewidth or lw = 1.5
marker = None
markeredgecolor or mec = #ff7f0e
markeredgewidth or mew = 1.0
markerfacecolor or mfc = #ff7f0e
markerfacecoloralt or mfcalt = none
zorder = 2
...
而 plt.setp 能够更改属性在没有任何参数的对象上调用 this 会打印出该对象能够承受的属性值:
>>> plt.setp(l2)
...
linestyle or ls: {'-', '--', '-.', ':', '', (offset, on-off-seq), ...}
linewidth or lw: float
sketch_params: (scale: float, length: float, randomness: float)
snap: bool or None
zorder: float
...
要打印单个属性的可能值,能够将属性的名称作为字符串输出 setp:
>>> plt.setp(l2, "linestyle")
linestyle: {'-', '--', '-.', ':', '', (offset, on-off-seq), ...}
批改属性的办法如下:
>>> plt.setp(l2, linestyle="-.", lw=5, color="red", alpha=0.5)
[None, None, None, None]
要查看更改后的以后图形,只需在图形对象上调用 get_figure:
fig.get_figure()
第二行的款式曾经变了
4、Legends
Legends 能够不便的通知咱们图中每个组件的含意, 默认是这样显示的:
x = np.linspace(0, 2, 100)
fig, ax = plt.subplots() # Create a figure and an axes.
l1 = ax.plot(x, x, label="linear")
l2 = ax.plot(x, x ** 2, label="quadratic")
l3 = ax.plot(x, x ** 3, label="cubic")
ax.set_title("Simple Plot")
ax.legend()
plt.show()
咱们能够调整他的参数,例如:
图例的地位、字体属性、大小,色彩,款式、图例中的列数,等等
能够在创立前设置,也能够在创立后应用 get_legend 提取,并应用 getp、setp 函数。
5、cycler
你有没有想过 Matplotlib 是如何本人扭转色彩或循环不同格调的?
在底层,Matplotlib 应用名为 Cyclers 的 Python 内置对象:
from cycler import cycler
c1 = cycler(arg1=[1, 2, 3, 4])
>>> c1
这个循环函数承受任何键值参数并创立一个字典列表:
c2 = cycler(arg2=list("rgba"))
for i in c2:
print(i)
------------------------------
{'arg2': 'r'}
{'arg2': 'g'}
{'arg2': 'b'}
{'arg2': 'a'}
还能够将多个循环器与“plus”和“multiply”操作符组合起来,这样能够取得索引到索引或穷举的参数组合:
for i in c1 + c2:
print(i)
--------------------------------
{'arg1': 1, 'arg2': 'r'}
{'arg1': 2, 'arg2': 'g'}
{'arg1': 3, 'arg2': 'b'}
{'arg1': 4, 'arg2': 'a'}
将这个自定义循环器并将其传递给 Matplotlib,就能够定制款式。上面,咱们创立四种不同的线条款式,容许 Matplotlib 循环应用不同的线条色彩,款式和大小:
line_prop_cycler = (cycler(color=list("rgcy"))
+ cycler(ls=["-", "--", "-.", ":"])
+ cycler(lw=[3, 6, 9, 12])
)
能够应用 axes 对象的 set_prop_cycle 函数将这个自定义循环器传递给绘图:
x = np.linspace(0, 2 * np.pi, 50)
offsets = np.linspace(0, 2 * np.pi, 4, endpoint=False)
yy = np.transpose([np.sin(x + phi) for phi in offsets])
fig, ax = plt.subplots(figsize=(8, 4))
ax.set_prop_cycle(line_prop_cycler) # Set propcycle before plotting
ax.plot(x, yy)
plt.show();
rcParams 字典中默认设置如下:
rcParams["axes.prop_cycle"]
咱们能够间接批改
6、tick_params
轴刻度应该精确地传播数据点及其单位的最小值和最大值,并显示几个要害的检查点,以便在不同的绘图局部之间进行比拟。
大多数 tick 属性能够应用 axes 对象的 tick_params 函数来管制。以下是文档中的例子:
>>> ax.tick_params()
Parameters
----------
axis : {'x', 'y', 'both'}, default: 'both'
The axis to which the parameters are applied.
which : {'major', 'minor', 'both'}, default: 'major'
The group of ticks to which the parameters are applied.
reset : bool, default: False
Whether to reset the ticks to defaults before updating them.
Other Parameters
----------------
direction : {'in', 'out', 'inout'}
Puts ticks inside the axes, outside the axes, or both.
length : float
Tick length in points.
width : float
Tick width in points.
color : color
Tick color.
首先应该指定的两个参数是 axis 和 which。这些参数将利用于 X 或 Y 轴刻度,以及最小和最大刻度。
大多数时候,在 Matplotlib 中不会看到小刻度。如果须要能够应用 axes 对象上的 minortics_on 函数:
fig, ax = plt.subplots(figsize=(3, 2))
>>> ax.minorticks_on()
7、Tickers
如果不像自定义 tick 参数(因为很麻烦)。能够应用许多内置的 Matplotlib 的“主题”汇合 (称为 tickers)。
from matplotlib import ticker
dir(ticker)
['AutoLocator',
'AutoMinorLocator',
'EngFormatter',
'FixedFormatter',
'FixedLocator',
'FormatStrFormatter',
'Formatter',
'FuncFormatter',
'IndexFormatter',
'IndexLocator',
'Integral',
'LinearLocator',
]
在 ticker 模块下有许多这样的子模块。个别状况下题目中带有 Locator 的控件管制刻度的地位。而 Formatters 则示意标签的款式。抉择好后能够应用上面的形式进行设置:
from matplotlib.ticker import EngFormatter
ax.xaxis.set_major_formatter(EngFormatter())
应用 axes 对象的 xaxis 或 yaxis 属性,调用 set_major(minor)_formatter(locator) 函数,并传入类名。
8、grid
自定义网格线能够突出数据范畴。在 Matplotlib 中,能够应用轴线对象的网格函数创立和自定义网格。上面是一个垂直网格的例子:
fig, ax = plt.subplots()
ax.grid(axis="x", linestyle=":", lw=3, color="r")
9、bar_label
条形图在数据分析中很常见。它们最重要的中央就是每个条的高度,条形标签能够突出每个条的显示。
bar_label 函数承受一个 BarContainer 对象作为参数,并主动标注每个 bar 的高度。
上面是 Seaborn 的一个简略的计数图:
import seaborn as sns
diamonds = sns.load_dataset("diamonds")
ax = sns.countplot(diamonds["cut"])
每次应用 Seaborn 或 ax.bar 等函数创立 barplot 时,BarContainer 对象都会被增加到图中。能够应用 axes 对象的 containers 属性来检索这个容器对象:
ax.containers
[<BarContainer object of 5 artists>]
在下面的列表中有一个 BarContainer 对象有 5 个 bar。咱们只需在创立了 plot 之后将这个对象传递给 bar_label:
ax = sns.countplot(diamonds["cut"])
ax.bar_label(ax.containers[0], padding=1)
ax.set_ylim(0, 25000)
plt.show();
10、zorder
当有很多图的时候,显示程序是十分重要的。你须要确保在画布上以适当的程序绘制每个图形,就须要 zorder 参数。
上面,咱们用不同的 zorders 创立了三行:
x = np.linspace(0, 7.5, 100)
plt.plot(x, np.sin(x), label="zorder=2", zorder=2) # bottom
plt.plot(x, np.sin(x + 0.5), label="zorder=3", zorder=3)
plt.axhline(0, label="zorder=2.5", color="lightgrey", zorder=2.5)
plt.title("Custom order of elements")
l = plt.legend(loc="upper right")
l.set_zorder(2.5) # legend between blue and orange line
plt.show()
能够看到 zorder 越大,就会在最上方显示, 笼罩掉小的组件。
总结
Matplotlib 在 2023 年 6 月的下载量超过 3000 万,简直是其最大竞争对手 Plotly 的 4 倍。Matplotlib 的胜利不仅仅在于它的简略(只须要几行代码就能生成简略的图形),还在于他的功能强大,然而要应用这些弱小的性能就须要应用他的高级性能,然而这些高级性能往往须要比较复杂的配置或者参数,须要咱们浏览官网的文档。所以才呈现了 seaborn,他将 Matplotlib 进行了整合不仅简略而且难看。
然而有时咱们须要更深刻的定制性能,seaborn 兴许还达不到咱们的指标,咱们只能本人定义的参数,本文总结的是个高级技巧能够轻松的帮你残缺自定义 Matplotlib 的工作。
https://avoid.overfit.cn/post/fece2cde8dbd4f899de00f5509385c6c
作者:Bex T