Matplotlib 可视化之图例与标签高级应用
作者 | 云朵君
装饰物指的是你可以添加到一个图形上的所有额外元素,以美化它或使它更清晰。装饰物包括图例、注释、颜色条、文本等标准元素,但也可以专门设计自己的元素。今天一起继续学习图例与标签元素的应用实例。
配置图例
ax.legend(loc='upper left',
frameon=False,
edgecolor="None")
完整代码解析
上下滑动查看更多源码
fig = plt.figure(figsize=(9.6, 4))
ax = plt.subplot(
xlim=[-np.pi, np.pi],
xticks=[-np.pi, -np.pi / 2, 0, np.pi / 2, np.pi],
xticklabels=["$-\pi$", "$-\pi/2$", "0", "$+\pi/2$", "$+\pi$"],
ylim=[-1, 1],
yticks=[-1, 0, 1],
yticklabels=["-1", "0", "+1"],
)
X = np.linspace(-np.pi, np.pi, 256, endpoint=True)
C, S = np.cos(X), np.sin(X)
# 绘制两条折线,颜色默认
ax.plot(X, C, label="$cos(x)$", clip_on=False)
ax.plot(X, S, label="$sin(x)$", clip_on=False)
# 隐藏上右边的轴线
ax.spines["right"].set_visible(False)
ax.spines["top"].set_visible(False)
# 移动下左边的轴线
ax.spines["left"].set_position(("data", -3.25))
ax.spines["bottom"].set_position(("data", -1.25))
ax.legend(edgecolor="None",loc=2,frameon=False)
详细代码解析
上下滑动查看更多源码
X = np.linspace(-np.pi, np.pi, 400, endpoint=True)
C, S = np.cos(X), np.sin(X)
plot1, plot2 = plot(ax) # 绘制折线图的对象
# --------------------P1-------------------------
# 用小横线标注在折线旁边
ax.text(
X[-1], C[-1],
" — " + plot1.get_label(), # 从对象中获取标签
color=plot1.get_color(), # 从对象中获取线条颜色
size="small", ha="left", va="center",)
# --------------------P2--------------------------
# 标注在对应折线上,且有透明边框
ax.text(
X[100], C[100],
" " + plot1.get_label(),
bbox=dict(facecolor="white", edgecolor="None", alpha=0.85),
color=plot1.get_color(),
ha="center", va="center", size="small",
rotation=42.5,)
# --------------------P3--------------------------
# 使用箭头
ax.annotate(
"$cos(x)$",
(X[100], C[100]),
size="medium",
color=plot1.get_color(),
xytext=(-50, +10),
textcoords="offset points",
arrowprops=dict(
arrowstyle="->", color=plot1.get_color(),
connectionstyle="arc3,rad=-0.3"),)
# --------------------P4--------------------------
# 圈点和注释的组合
index = 10
ax.scatter(
[X[index]], [C[index]],
s=100, marker="o", zorder=10,
edgecolor=plot1.get_color(),
facecolor="white", linewidth=1, clip_on=False,)
ax.text(
X[index], 1.01 * C[index],
"A",
zorder=20,size="small",
color=plot1.get_color(),
ha="center", va="center", clip_on=False,)
标题和标签
set_title
、set_xlabel
和 set_ylabel
方法操作了标题和标签。当仅仅使用默认参数时,确实比较方便。并且它们的默认位置通常对大多数图表都比较合适。尽管如此,仍然可以使用各种参数来定制和美化图形。完整代码解析
ax.legend(
edgecolor="None",
ncol=2,
loc="upper right",
bbox_to_anchor=(1.01, 1.225),
# 用于与loc一起定位图例的框。(x, y, width, height)
borderaxespad=1,
# 轴线和图例边框之间的填充,以字体大小为单位。
)
# 设置标题
ax.set_title("三角函数", x=1, y=1.2, ha="right",size=14)
# 设置x轴标签
ax.set_xlabel("角度", va="center", weight="bold",size=12)
ax.xaxis.set_label_coords(0.5, -0.25)
# 设置标签的坐标。
# 默认情况下,y 标签的 x 坐标和 x 标签的 y 坐标由刻度标签边界框确定,
# 但是如果有多个轴,这可能会导致多个标签对齐不良。
# 设置y轴标签
ax.set_ylabel("值", ha="center", weight="bold",size=12)
ax.yaxis.set_label_coords(-0.025, 0.5)
make_axes_locatable
方法来划分每个轴,并为标题区域预留15%的高度。在这个图中,还用Latex 插入了一个完全对齐的文本,它可以被看作是另一种形式或(高级)装饰。注释
在matplotlib中,注释可能是最难处理的对象。原因是它包含的概念众多,而这些概念又具有大量的参数。此外,由于注释所涉及的文本大小是按点排列的,这无疑又是雪上加霜。此外可能需要混合使用像素、点、分数或数据单元中的绝对坐标或相对坐标。你可以这么认为,你可以对具有任何类型投影的任何轴进行注释,那么你现在应该可以理解到为什么annotate方法提供这么多参数。
上面这段话比较抽象,接下来我们一起看下具体例子。注释图形最简单的方法是在想要注释的点附近添加标签,如下图所示。图中,为了使得标签独立于数据分布保持可读性,为标签添加了一个白色的轮廓。然而,如果这样的点过多,所有不同的标签可能会使图形变得混乱,并可能会掩盖潜在的重要信息。
完整代码解析
上下滑动查看更多源码
import matplotlib.patheffects as path_effects
fig = plt.figure(figsize=(10, 5))
ax = plt.subplot(1, 2, 1, xlim=[-1, +1],
xticks=[], ylim=[-1, +1],
yticks=[], aspect=1)
# ---------------------------------------------
# 绘制散点图
np.random.seed(123)
X = np.random.normal(0, 0.35, 1000)
Y = np.random.normal(0, 0.35, 1000)
ax.scatter(X, Y, edgecolor="None", s=60,
facecolor="C1", alpha=0.5)
# 不重复采用:array([1, 4, 0, 3, 2])
I = np.random.choice(len(X), size=5,
replace=False)
# 根据y值,从大到小排序
Px, Py = X[I], Y[I]
I = np.argsort(Y[I])[::-1]
Px, Py = Px[I], Py[I]
# 将随机选取的五个点用黑色边框框选出
ax.scatter(Px, Py, edgecolor="black", facecolor="white", zorder=20)
ax.scatter(Px, Py, edgecolor="None", facecolor="C1", alpha=0.5, zorder=30)
添加标签注释
for i in range(len(I)):
# 五个注释是样式是一样的,可以使用循环添加
text = ax.annotate(
"Point " + chr(ord("A") + i),
xy=(Px[i], Py[i]),
xycoords="data",
xytext=(0, 18),
textcoords="offset points",
ha="center",
size="medium",
arrowprops=dict(
arrowstyle="->", shrinkA=0, shrinkB=5, color="black", linewidth=0.75),
)
text.set_path_effects(
[path_effects.Stroke(linewidth=2, foreground="white"), path_effects.Normal()]
)
text.arrow_patch.set_path_effects(
[path_effects.Stroke(linewidth=2, foreground="white"), path_effects.Normal()]
)
X = np.random.normal(0, .35, 1000)
Y = np.random.normal(0, .35, 1000)
ax.scatter(X, Y, edgecolor="None",
facecolor="C1", alpha=0.5)
I = np.random.choice(len(X), size=5, replace=False)
Px, Py = X[I], Y[I]
I = np.argsort(Y[I])[::-1]
Px, Py = Px[I], Py[I]
上下滑动查看更多源码
y, dy = 0.25, 0.125
style = "arc,angleA=-0,angleB=0,armA=-100,armB=0,rad=0"
for i in range(len(I)):
text = ax2.annotate(
"Point " + chr(ord("A") + i),
xy=(Px[i], Py[i]),
xycoords="data",
xytext=(1.25, y - i * dy),
textcoords="data",
arrowprops=dict(
arrowstyle="->",
color="black",
linewidth=0.75,
shrinkA=20,
shrinkB=5,
patchA=None,
patchB=None,
connectionstyle=style,
),
)
text.arrow_patch.set_path_effects(
[path_effects.Stroke(linewidth=2, foreground="white"), path_effects.Normal()]
)
完整代码解析
上下滑动查看更多源码
from matplotlib.gridspec import GridSpec
from matplotlib.patches import Rectangle, ConnectionPatch
# 设置画布
fig = plt.figure(figsize=(6, 5))
n = 5
gs = GridSpec(n, n + 1)
ax = plt.subplot( gs[:n, :n],
xlim=[-1, +1], xticks=[],
ylim=[-1, +1], yticks=[], aspect=1)
# 绘制散点图略(见上面代码)
dx, dy = 0.075, 0.075
for i, (x, y) in enumerate(zip(Px, Py)):
# 设置子画布
sax = plt.subplot(
gs[i, n],
xlim=[x - dx, x + dx],
xticks=[],
ylim=[y - dy, y + dy],
yticks=[],
aspect=1,)
# 在子画布上绘制散点
sax.scatter(X, Y, edgecolor="None",
facecolor="C1", alpha=0.5,s=60)
sax.scatter(Px, Py, edgecolor="black",
facecolor="None", linewidth=0.75,s=60)
# 加上注释
sax.text(
1.1, 0.5,
"Point " + chr(ord("A") + i),
rotation=90, size=8, ha="left", va="center",
transform=sax.transAxes, )
# 绘制矩形
rect = Rectangle(
(x - dx, y - dy),
2 * dx, 2 * dy,
edgecolor="black", facecolor="None",
linestyle="--", linewidth=0.75, )
ax.add_patch(rect)
# 绘制连接补丁Patch
con = ConnectionPatch(
xyA=(x, y), coordsA=ax.transData,
xyB=(0, 0.5), coordsB=sax.transAxes,
linestyle="--", linewidth=0.75,
patchA=rect, arrowstyle="->", )
fig.add_artist(con)
GridSpec
:指定子图将放置的网格的几何位置。需要设置网格的行数和列数。子图布局参数(例如,左,右等)可以选择性调整。ConnectionPatch
:用于在两点之间建立连接线。上下滑动查看更多参数
参数:
xyA: 它是x-y图上也称为点A的连接线的起点。 xyB: 它是x-y图上连接线的起点,也称为点B。 coordsA: A点的坐标。 coordsB: B点的坐标。 axesA: 它是x-y图上连接轴的起点。 axesB: 它是x-y图上连接轴的终点。 arrowstyle: 用于设置连接箭头的样式。其默认类型为“-”。 arrow_transmuter: 用于忽略连接线。 connectionstyle: 它描述了posA和posB的连接方式。它可以是ConnectionStyle类的实例,也可以是connectionstyle名称的字符串,它具有可选的逗号分隔属性。 connector: 通常忽略它,并决定忽略哪个连接器。 patchA: 用于在A点添加补丁。 patchB: 用于在B点添加补丁 shrinkA: 用于在A点收缩连接器。 shrinkB: 用于在B点收缩连接器。 mutation_scale: 箭头样式的属性(例如head_length)的缩放比例值。 mutation_aspect: 变异前,矩形的高度将被该值挤压,变异框将被其倒数拉伸。 clip_on: 设置艺术家是否使用剪辑。 dpi_cor: dpi_cor当前用于linewidth-related事物和收缩因子。突变规模受此影响。
参考资料
latex-text-box: https://github.com/rougier/scientific-visualization-book/blob/master/code/ornaments/latex-text-box.py
[2]Scientific Visualisation-Python & Matplotlib
往 期 回 顾 资讯 资讯 技术 技术 分享
点收藏
点点赞
点在看
关注公众号:拾黑(shiheibook)了解更多
[广告]赞助链接:
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/