簡體   English   中英

Matplotlib:子圖注釋的正確放置?

[英]Matplotlib: correct placement of subplot annotations?

我想通過循環我的數據來創建帶有Matplotlib的子圖。 但是,我沒有將注釋放入正確的 position中,顯然甚至沒有進入正確的子圖。 此外,常見的 x 軸和 y 軸標簽也不起作用。

我的真實數據更復雜,但這里有一個重現錯誤的示例:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
import seaborn as sns

# create data
distributions = []
first_values = []
second_values = []
for i in range(4):
    distributions.append(np.random.normal(0, 0.5, 100))
    first_values.append(np.random.uniform(0.7, 1))
    second_values.append(np.random.uniform(0.7, 1))

# create subplot
fig, axes = plt.subplots(2, 2, figsize = (15, 10))
legend_elements = [Line2D([0], [0], color = '#76A29F', lw = 2, label = 'distribution'),
                   Line2D([0], [0], color = '#FEB302', lw = 2, label = '1st value', linestyle = '--'),
                   Line2D([0], [0], color = '#FF5D3E', lw = 2, label = '2nd value')]

# loop over data and create subplots    
for data in range(4):
    if data == 0:
        position = axes[0, 0]
    if data == 1:
        position = axes[0, 1]
    if data == 2:
        position = axes[1, 0]
    if data == 3:
        position = axes[1, 1]
        
    dist = distributions[data]
    first = first_values[data]
    second = second_values[data]
        
    sns.histplot(dist, alpha = 0.5, kde = True, stat = 'density', bins = 20, color = '#76A29F', ax = position)
    sns.rugplot(dist, alpha = 0.5, color = '#76A29F', ax = position)
    position.annotate(f'{np.mean(dist):.2f}', (np.mean(dist), 0.825), xycoords = ('data', 'figure fraction'), color = '#76A29F')
    position.axvline(first, 0, 0.75, linestyle = '--', alpha = 0.75, color = '#FEB302')
    position.axvline(second, 0, 0.75, linestyle = '-', alpha = 0.75, color = '#FF5D3E')
    position.annotate(f'{first:.2f}', (first, 0.8), xycoords = ('data', 'figure fraction'), color = '#FEB302')
    position.annotate(f'{second:.2f}', (second, 0.85), xycoords = ('data', 'figure fraction'), color = '#FF5D3E')
    position.set_xticks(np.arange(round(min(dist), 1) - 0.1, round(max(max(dist), max([first]), max([second])), 1) + 0.1, 0.1))

plt.xlabel("x-axis name")
plt.ylabel("y-axis name")
plt.legend(handles = legend_elements, bbox_to_anchor = (1.5, 0.5))
plt.show()

生成的 plot 如下所示: 在此處輸入圖像描述

我想要的是擁有

  1. 垂直線旁邊正確子圖中的注釋/分布的平均值
  2. 所有子圖或至少每行/列的共享 x 和 y 標簽

非常感謝任何幫助!

如果使用 function 將 subplot 制作為單個數組(axes.flatten())並修改為順序繪制圖形,則可以繪制圖形。 出於測試目的,注釋的 colors 已部分更改。

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
import seaborn as sns

np.random.seed(202000104)
# create data
distributions = []
first_values = []
second_values = []
for i in range(4):
    distributions.append(np.random.normal(0, 0.5, 100))
    first_values.append(np.random.uniform(0.7, 1))
    second_values.append(np.random.uniform(0.7, 1))
    
fig, axes = plt.subplots(2, 2, figsize=(15, 10))

legend_elements = [Line2D([0], [0], color = '#76A29F', lw = 2, label = 'distribution'),
                   Line2D([0], [0], color = '#FEB302', lw = 2, label = '1st value', linestyle = '--'),
                   Line2D([0], [0], color = '#FF5D3E', lw = 2, label = '2nd value')]

for i,ax in enumerate(axes.flatten()):
    sns.histplot(distributions[i], alpha=0.5, kde=True, stat='density', bins=20, color='#76A29F', ax=ax)
    sns.rugplot(distributions[i], alpha=0.5, color='#76A29F', ax=ax)
    ax.annotate(f'{np.mean(distributions[i]):.2f}', (np.mean(distributions[i]), 0.825), xycoords='data', color='red')
    ax.axvline(first_values[i], 0, 0.75, linestyle = '--', alpha = 0.75, color = '#FEB302')
    ax.axvline(second_values[i], 0, 0.75, linestyle = '-', alpha = 0.75, color = '#FF5D3E')
    ax.annotate(f'{first_values[i]:.2f}', (first_values[i], 0.8), xycoords='data', color='#FEB302')
    ax.annotate(f'{second_values[i]:.2f}', (second_values[i], 0.85), xycoords='data', color = '#FF5D3E')
    ax.set_xticks(np.arange(round(min(distributions[i]), 1) - 0.1, round(max(max(distributions[i]), max([first_values[i]]), max([second_values[i]])), 1) + 0.1, 0.1))

plt.xlabel("x-axis name")
plt.ylabel("y-axis name")
plt.legend(handles = legend_elements, bbox_to_anchor = (1.35, 0.5))

plt.show()

在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM