dede回到列表頁(yè)的代碼(debug怎么返回到上一級(jí))
裝飾物指的是你可以添加到一個(gè)圖形上的所有額外元素,以美化它或使它更清晰。裝飾物包括圖例、注釋、顏色條、文本等標(biāo)準(zhǔn)元素,但也可以專(zhuān)門(mén)設(shè)計(jì)自己的元素。上篇Matplotlib 可視化之注釋與文本高級(jí)應(yīng)用一文中,已經(jīng)接觸了注釋與文本的應(yīng)用實(shí)例,今天和云朵君一起繼續(xù)學(xué)習(xí)圖例與標(biāo)簽元素的應(yīng)用實(shí)例。
配置圖例
想在可視化圖形中使用圖例,可以為不同的圖形元素分配標(biāo)簽。
圖例非常容易使用,只要求用戶(hù)命名圖。Matplotlib將自動(dòng)創(chuàng)建一個(gè)包含每個(gè)圖形元素的圖例。即使在大多數(shù)情況下,一個(gè)簡(jiǎn)單的legend() 調(diào)用就足夠了,但圖例還是提供了幾個(gè)選項(xiàng),允許我們自定義圖例的各個(gè)配置。如使用
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)
# 繪制兩條折線,顏色默認(rèn)
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)
# 移動(dòng)下左邊的軸線
ax.spines["left"].set_position(("data", -3.25))
ax.spines["bottom"].set_position(("data", -1.25))
ax.legend(edgecolor="None",loc=2,frameon=False)
然而,在某些情況下,用圖例來(lái)添加信息可能不是最合適的方式。例如,當(dāng)你有多個(gè)圖表時(shí),讀者在閱讀圖表,視線在圖表和圖例之間來(lái)回切換時(shí),可能會(huì)覺(jué)得很乏味。另一種可以解決此類(lèi)困惑的方法是在下圖所示的圖上直接添加信息。
詳細(xì)代碼解析
X = np.linspace(-np.pi, np.pi, 400, endpoint=True)
C, S = np.cos(X), np.sin(X)
plot1, plot2 = plot(ax) # 繪制折線圖的對(duì)象
# --------------------P1-------------------------
# 用小橫線標(biāo)注在折線旁邊
ax.text(
X[-1], C[-1],
" — " + plot1.get_label(), # 從對(duì)象中獲取標(biāo)簽
color=plot1.get_color(), # 從對(duì)象中獲取線條顏色
size="small", ha="left", va="center",)
# --------------------P2--------------------------
# 標(biāo)注在對(duì)應(yīng)折線上,且有透明邊框
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--------------------------
# 圈點(diǎn)和注釋的組合
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,)
當(dāng)然,這里是沒(méi)有最好的選擇,因?yàn)樗娴娜Q于數(shù)據(jù)。對(duì)于上述的sin / cos的示例(非常簡(jiǎn)單),這四種解決方案都是合適的,但當(dāng)有很多實(shí)際數(shù)據(jù)一起使用時(shí),可能這種方法就失效了。此時(shí)我們可能需要尋求其他方式來(lái)標(biāo)記數(shù)據(jù),如將圖分成幾個(gè)圖分別展示。
展開(kāi)全文
標(biāo)題和標(biāo)簽
我們已經(jīng)使用 set_title、set_xlabel 和 set_ylabel 方法操作了標(biāo)題和標(biāo)簽。當(dāng)僅僅使用默認(rèn)參數(shù)時(shí),確實(shí)比較方便。并且它們的默認(rèn)位置通常對(duì)大多數(shù)圖表都比較合適。盡管如此,仍然可以使用各種參數(shù)來(lái)定制和美化圖形。
如下面兩個(gè)圖所示,對(duì)比觀察,可以明顯發(fā)現(xiàn):上圖大部分使用了默認(rèn)參數(shù)。而下圖中,用軸標(biāo)簽替換軸刻度標(biāo)簽,即在軸中間加上說(shuō)明標(biāo)簽,為了使其更靠近軸,刪除了可能與標(biāo)簽碰撞的中心刻度。此外,將標(biāo)題其向右移動(dòng),并相應(yīng)地移動(dòng)圖例框,將其放置在標(biāo)題下方,并且使用一行兩列的排列方式。其實(shí)這里沒(méi)有做過(guò)復(fù)雜的操作,但我認(rèn)為結(jié)果在視覺(jué)上更驚艷。
完整代碼解析
ax.legend(
edgecolor="None",
ncol=2,
loc="upper right",
bbox_to_anchor=(1.01, 1.225),
# 用于與loc一起定位圖例的框。(x, y, width, height)
borderaxespad=1,
# 軸線和圖例邊框之間的填充,以字體大小為單位。
)
# 設(shè)置標(biāo)題
ax.set_title("三角函數(shù)", x=1, y=1.2, ha="right",size=14)
# 設(shè)置x軸標(biāo)簽
ax.set_xlabel("角度", va="center", weight="bold",size=12)
ax.xaxis.set_label_coords(0.5, -0.25)
# 設(shè)置標(biāo)簽的坐標(biāo)。
# 默認(rèn)情況下,y 標(biāo)簽的 x 坐標(biāo)和 x 標(biāo)簽的 y 坐標(biāo)由刻度標(biāo)簽邊界框確定,
# 但是如果有多個(gè)軸,這可能會(huì)導(dǎo)致多個(gè)標(biāo)簽對(duì)齊不良。
# 設(shè)置y軸標(biāo)簽
ax.set_ylabel("值", ha="center", weight="bold",size=12)
ax.yaxis.set_label_coords(-0.025, 0.5)
在某些情況下(如會(huì)議海報(bào)),可能需要讓標(biāo)題更吸引眼球,如下圖所示。這可以通過(guò)使用make_axes_locatable 方法來(lái)劃分每個(gè)軸,并為標(biāo)題區(qū)域預(yù)留15%的高度。在這個(gè)圖中,還用Latex 插入了一個(gè)完全對(duì)齊的文本,它可以被看作是另一種形式或(高級(jí))裝飾。
完整代碼參見(jiàn)latex-text-box[1]
注釋
在matplotlib中,注釋可能是最難處理的對(duì)象。原因是它包含的概念眾多,而這些概念又具有大量的參數(shù)。此外,由于注釋所涉及的文本大小是按點(diǎn)排列的,這無(wú)疑又是雪上加霜。此外可能需要混合使用像素、點(diǎn)、分?jǐn)?shù)或數(shù)據(jù)單元中的絕對(duì)坐標(biāo)或相對(duì)坐標(biāo)。你可以這么認(rèn)為,你可以對(duì)具有任何類(lèi)型投影的任何軸進(jìn)行注釋?zhuān)敲茨悻F(xiàn)在應(yīng)該可以理解到為什么annotate方法提供這么多參數(shù)。
上面這段話比較抽象,接下來(lái)我們一起看下具體例子。注釋圖形最簡(jiǎn)單的方法是在想要注釋的點(diǎn)附近添加標(biāo)簽,如下圖所示。圖中,為了使得標(biāo)簽獨(dú)立于數(shù)據(jù)分布保持可讀性,為標(biāo)簽添加了一個(gè)白色的輪廓。然而,如果這樣的點(diǎn)過(guò)多,所有不同的標(biāo)簽可能會(huì)使圖形變得混亂,并可能會(huì)掩蓋潛在的重要信息。
完整代碼解析
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)
# ---------------------------------------------
# 繪制散點(diǎn)圖
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)
# 不重復(fù)采用:array([1, 4, 0, 3, 2])
I = np.random.choice(len(X), size=5,
replace=False)
# 根據(jù)y值,從大到小排序
Px, Py = X[I], Y[I]
I = np.argsort(Y[I])[::-1]
Px, Py = Px[I], Py[I]
# 將隨機(jī)選取的五個(gè)點(diǎn)用黑色邊框框選出
ax.scatter(Px, Py, edgecolor="black", facecolor="white", zorder=20)
ax.scatter(Px, Py, edgecolor="None", facecolor="C1", alpha=0.5, zorder=30)
添加標(biāo)簽注釋
for i in range(len(I)):
# 五個(gè)注釋是樣式是一樣的,可以使用循環(huán)添加
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()]
)
另一種方法是將標(biāo)簽推到圖的一側(cè),并使用虛線來(lái)建立點(diǎn)和標(biāo)簽之間的鏈接,如下圖所示。
但這些形狀、位置、排列方式等樣式的設(shè)計(jì)并不是圖形自動(dòng)的,為了繪制出該圖形,就必須計(jì)算幾乎所有的東西。
首先,為了不讓線相互交叉,將目標(biāo)標(biāo)記的點(diǎn)排序:
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]
從這些點(diǎn)開(kāi)始,使用一個(gè)相當(dāng)復(fù)雜的連接樣式來(lá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()]
)
也可以使用連接補(bǔ)片的方式在軸外來(lái)注釋的目標(biāo)對(duì)象,如下圖所示。
該圖中,創(chuàng)建了幾個(gè)矩形,在一些點(diǎn)周?chē)@示感興趣的區(qū)域,并創(chuàng)建了與相應(yīng)的縮放軸的連接。注意連接開(kāi)始在外面的矩形,這是一個(gè)不錯(cuò)的功能提供的注釋?zhuān)嚎梢灾付▽?duì)象的性質(zhì)要注釋(通過(guò)提供一個(gè)patche)和matplotlib會(huì)照顧的連接邊界的起源的patche。
完整代碼解析
from matplotlib.gridspec import GridSpec
from matplotlib.patches import Rectangle, ConnectionPatch
# 設(shè)置畫(huà)布
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)
# 繪制散點(diǎn)圖略(見(jiàn)上面代碼)
dx, dy = 0.075, 0.075
for i, (x, y) in enumerate(zip(Px, Py)):
# 設(shè)置子畫(huà)布
sax = plt.subplot(
gs[i, n],
xlim=[x - dx, x + dx],
xticks=[],
ylim=[y - dy, y + dy],
yticks=[],
aspect=1,)
# 在子畫(huà)布上繪制散點(diǎn)
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)
# 繪制連接補(bǔ)丁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:指定子圖將放置的網(wǎng)格的幾何位置。需要設(shè)置網(wǎng)格的行數(shù)和列數(shù)。子圖布局參數(shù)(例如,左,右等)可以選擇性調(diào)整。
ConnectionPatch:用于在兩點(diǎn)之間建立連接線。
參數(shù):
xyA: 它是x-y圖上也稱(chēng)為點(diǎn)A的連接線的起點(diǎn)。
xyB: 它是x-y圖上連接線的起點(diǎn),也稱(chēng)為點(diǎn)B。
coordsA: A點(diǎn)的坐標(biāo)。
coordsB: B點(diǎn)的坐標(biāo)。
axesA: 它是x-y圖上連接軸的起點(diǎn)。
axesB: 它是x-y圖上連接軸的終點(diǎn)。
arrowstyle: 用于設(shè)置連接箭頭的樣式。其默認(rèn)類(lèi)型為“-”。
arrow_transmuter: 用于忽略連接線。
connectionstyle: 它描述了posA和posB的連接方式。它可以是ConnectionStyle類(lèi)的實(shí)例,也可以是connectionstyle名稱(chēng)的字符串,它具有可選的逗號(hào)分隔屬性。
connector: 通常忽略它,并決定忽略哪個(gè)連接器。
patchA: 用于在A點(diǎn)添加補(bǔ)丁。
patchB: 用于在B點(diǎn)添加補(bǔ)丁
shrinkA: 用于在A點(diǎn)收縮連接器。
shrinkB: 用于在B點(diǎn)收縮連接器。
mutation_scale: 箭頭樣式的屬性(例如head_length)的縮放比例值。
mutation_aspect: 變異前,矩形的高度將被該值擠壓,變異框?qū)⒈黄涞箶?shù)拉伸。
clip_on: 設(shè)置藝術(shù)家是否使用剪輯。
dpi_cor: dpi_cor當(dāng)前用于linewidth-related事物和收縮因子。突變規(guī)模受此影響。
參考資料
[1]latex-text-box: https://github.com/rougier/scientific-visualization-book/blob/master/code/ornaments/latex-text-box.py
[2]Scientific Visualisation-Python Matplotlib
【聲明】本文版權(quán)歸原作者所有,內(nèi)容為作者個(gè)人觀點(diǎn),轉(zhuǎn)載目的在于傳遞更多信息,如涉及作品內(nèi)容、版權(quán)等問(wèn)題,可聯(lián)系本站刪除,謝謝。
掃描二維碼推送至手機(jī)訪問(wèn)。
版權(quán)聲明:本文由飛速云SEO網(wǎng)絡(luò)優(yōu)化推廣發(fā)布,如需轉(zhuǎn)載請(qǐng)注明出處。