本文示例程式碼、資料已上傳至我的
Github
倉庫https://github.com/CNFeffery/DataScienceStudyNotes
1 簡介
在進行資料視覺化時我們常常需要在視覺化作品上進行一些文字標註,譬如對散點圖我們可以將每個散點對應的屬性資訊標註在每個散點旁邊,但隨著散點量的增多,或影像上的某個區域聚集了較多的散點時,疊加上的文字標註會擠在一起相互疊置,出現如圖1所示的情況:
出現這種情況非常影響資料視覺化作品的呈現效果,而我們下面要介紹的adjustText
是一個輔助matplotlib
所繪製的影像自動調整文字位置以緩解遮擋現象的庫,其靈感來源於R
中非常著名的輔助ggplot2
解決文字遮擋問題的ggrepel
:
它通過演算法迭代,在一輪輪的迭代過程中逐漸消除文字遮擋現象:
下面我們就來學習如何使用adjustText
解決matplotlib
影像文字遮擋問題。
2 使用adjustText解決文字遮擋問題
2.1 從一個簡單的例子出發
使用pip install adjustText
或conda install -c conda-forge adjusttext
來安裝adjustText
。安裝成功之後,首先生成隨機示例資料以方便之後的演示:
import matplotlib.pyplot as plt
from adjustText import adjust_text
import numpy as np
#解決中文顯示問題
plt.rcParams['font.sans-serif'] = ['SimHei']
seed = np.random.RandomState(42) # 固定隨機數水平
x, y = seed.uniform(0, 1, [2, 100]) # 產生固定的均勻分佈隨機數
texts = [f'文字{i}' for i in range(x.__len__())]
接著我們先不使用adjustText
調整影像,直接繪製出原始的散點+文字標籤:
fig, ax = plt.subplots(figsize=(8, 8))
ax.scatter(x, y, c='SeaGreen', s=10) # 繪製散點
# 繪製所有點對應的文字標籤
for x_, y_, text in zip(x, y, texts):
plt.text(x_, y_, text, fontsize=12)
# 美觀起見隱藏頂部與右側邊框線
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
fig.savefig('圖4.png', dpi=300, bbox_inches='tight', pad_inches=0) # 儲存影像
可以看到,在通常的情況下,散點聚集的區域內文字標籤非常容易重疊在一起,接下來我們使用adjustText
的基礎功能來消除文字重疊現象:
這時可以看到與圖4相比,圖5中的所有文字都沒有出現彼此重疊現象,adjustText
幫助我們自動微調了文字的擺放位置,並且距離原始散點偏移較大的文字還貼心的加上了連線線,至此,我們就初探了adjustText
的強大功能,接下來我們來學習adjustText
的更多功能。
2.2 adjust_text的用法
adjustText
中的核心功能都通過呼叫函式adjust_text
來實現,其核心引數如下:
texts:List型,每個元素都是表示單個文字標籤對應的
matplotlib.text.Text
物件ax:繪製文字標籤的目標axe物件,預設為最近一次的axe物件
lim:int型,控制迭代調整文字標籤位置的次數,預設為500次
precision:float型,用於決定迭代停止的精度,預設為0.01,即所有標籤相互遮擋部分的長和寬佔所有標籤自身長寬之和的比例,
addjust_text
會在精度達到precision和迭代次數超過lim這兩個條件中至少有一個滿足時停止迭代only_move:字典型,用於指定文字標籤與不同物件發生遮擋時的位移策略,鍵有
'points'
、'text'
和'objects'
,對應的值可選'xy'
、'x'
、'y'
,分別代表豎直和水平方向均調整、只調整水平方向以及只調整豎直方向arrowprops:字典型,用於設定偏移後的文字標籤與原始位置之間的連線樣式,下文會作具體演示
save_steps:bool型,用於決定是否儲存記錄迭代過程中各輪的幀影像,預設為False
save_prefix:str型,當save_steps設定為True時,用於指定中間幀儲存的路徑,預設為'',即當前工作路徑
下面我們來演示一下這些引數的使用效果,首先我們來看看only_move
引數的效果,在圖6的基礎上,我們設定only_move={'text': 'x'}
,即當文字出現遮擋時,只在水平方向上進行偏移,這裡將save_steps設定為True以直觀地檢視偏移過程:
fig, ax = plt.subplots(figsize=(8, 8))
ax.scatter(x, y, c='SeaGreen', s=10) # 繪製散點
# 使用adjustText修正文字重疊現象
new_texts = [plt.text(x_, y_, text, fontsize=12) for x_, y_, text in zip(x, y, texts)]
adjust_text(new_texts,
only_move={'text': 'x'},
arrowprops=dict(arrowstyle='-', color='grey'),
save_steps=True)
# 美觀起見隱藏頂部與右側邊框線
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
fig, ax = plt.subplots(figsize=(8, 8))
ax.scatter(x, y, c='SeaGreen', s=10) # 繪製散點
# 使用adjustText修正文字重疊現象
new_texts = [plt.text(x_, y_, text, fontsize=12) for x_, y_, text in zip(x, y, texts)]
adjust_text(new_texts,
arrowprops=dict(arrowstyle='->',
color='red',
lw=1))
# 美觀起見隱藏頂部與右側邊框線
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
fig.savefig('圖7.png', dpi=300, bbox_inches='tight', pad_inches=0) # 儲存影像
這時連線隨著我們自定義的設定改變到相應的樣式:
有關adjustText
的更多引數設定資訊和示例可以去官方文件(https://adjusttext.readthedocs.io/en/latest/ )檢視。
以上就是本文的全部內容,如有疑問歡迎在評論區與我們討論。