我正在嘗試使用 seaborn 中的拆分小提琴圖繪制具有不同范圍的兩個變數。
這是我到目前為止所做的:
from matplotlib import pyplot as plt
import seaborn as sns
import numpy as np
df1 = pd.read_csv('dummy_metric1.csv')
df2 = pd.read_csv('dummy_metric2.csv')
fig, ax2 = plt.subplots()
sns.set_style('white')
palette1 = 'Set2'
palette2 = 'Set1'
colors_list = ['#78C850', '#F08030', '#6890F0', '#A8B820', '#F8D030', '#E0C068', '#C03028', '#F85888', '#98D8D8']
ax1 = sns.violinplot(y=df1.Value,x=df1.modality,hue=df1.metric, palette=palette1, inner="stick")
xlim = ax1.get_xlim()
ylim = ax1.get_ylim()
for violin in ax1.collections:
bbox = violin.get_paths()[0].get_extents()
x0, y0, width, height = bbox.bounds
violin.set_clip_path(plt.Rectangle((x0, y0), width / 2, height, transform=ax1.transData))
ax1.set_xlim(xlim)
ax1.set_ylim(ylim)
ax1.set_title("dummy")
ax1.set_ylabel("metric1")
ax1.set_xlabel("Modality")
ax1.set_xticklabels(ax1.get_xticklabels(), rotation=45, ha='right')
ax1.legend_.remove()
ax2 = ax1.twinx()
ax2 = sns.violinplot(y=df2.Value,x=df2.modality,hue=df2.metric, palette=palette2, inner=None)
xlim = ax2.get_xlim()
ylim = ax2.get_ylim()
for violin in ax2.collections:
bbox = violin.get_paths()[0].get_extents()
x0, y0, width, height = bbox.bounds
violin.set_clip_path(plt.Rectangle((x0, y0), width / 2, height, transform=ax2.transData))
ax2.set_xlim(xlim)
ax2.set_ylim(ylim)
ax2.set_ylabel("Metric2")
ax2.set_xticklabels(ax2.get_xticklabels(), rotation=45, ha='right')
ax2.legend_.remove()
fig.tight_layout()
plt.show()
但是,我無法使用 ax2 小提琴的正確部分。這是輸出。

當我這樣做時,violin.set_clip_path(plt.Rectangle((width/2, y0), width / 2, height, transform=ax2.transData))我得到了這個結果:

有人可以解釋我錯過了什么嗎?另外,我該如何管理inner="stick"?
TIA
uj5u.com熱心網友回復:
這是一種使用split=True虛擬資料強制拆分空一半的方法。對于左半部分,對于真實資料metric設定1為 ,2對于虛擬資料設定為 。反之亦然。我們需要確保所有資料框對modality列使用相同的分類順序,以避免混淆。
from matplotlib import pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
sns.set_style('white')
df1 = pd.DataFrame({'modality': pd.Categorical.from_codes(np.random.randint(0, 3, 30), ['a', 'b', 'c']),
'Value': np.random.rand(30) * 25 50})
df1['metric'] = 1
df1_dummy = pd.DataFrame({'modality': pd.Categorical.from_codes([0], ['a', 'b', 'c']), 'Value': [np.nan]})
df1_dummy['metric'] = 2
df2 = pd.DataFrame({'modality': pd.Categorical.from_codes(np.random.randint(0, 3, 100), ['a', 'b', 'c']),
'Value': np.random.randn(100).cumsum() / 10 1})
df2['metric'] = 2
df2_dummy = pd.DataFrame({'modality': pd.Categorical.from_codes([0], ['a', 'b', 'c']), 'Value': [np.nan]})
df2_dummy['metric'] = 1
ax1 = sns.violinplot(y='Value', x='modality', hue='metric', palette=['turquoise', 'red'],
inner="stick", split=True, data=pd.concat([df1, df1_dummy]))
ax1.legend_.remove()
ax1.set_ylabel('metric 1')
ax2 = ax1.twinx()
sns.violinplot(y='Value', x='modality', hue='metric', palette=['turquoise', 'red'],
inner="stick", split=True, data=pd.concat([df2, df2_dummy]), ax=ax2)
ax2.set_ylabel('metric 2')
plt.tight_layout()
plt.show()

PS:這是原始代碼的可能改編:
- 使用
plt.Rectangle((x0 width/2, y0), width/2, height)夾上AX2小提琴 - 使用
ax=引數 ofsns.violinplot()指示正確的子圖 - 不改變斧頭的 xlim 和 ylim
- 確保兩個資料幀使用相同的分類順序
modality - 剪輯“內部”行, for
ax1:回圈遍歷這些行,獲取它們的x0andx1,并將該行縮短為x0and(x0 x1)/2 - 類似于 for
ax2:遍歷各行,獲取它們的x0andx1,并將該行縮短為(x0 x1)/2andx1 - 更新圖例以
ax2將其與 的圖例相結合ax1,然后洗掉ax1的圖例
from matplotlib import pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
df1 = pd.DataFrame({'modality': pd.Categorical.from_codes(np.random.randint(0, 3, 30), ['a', 'b', 'c']),
'Value': np.random.rand(30) * 25 50})
df1['metric'] = 1
df2 = pd.DataFrame({'modality': pd.Categorical.from_codes(np.random.randint(0, 3, 100), ['a', 'b', 'c']),
'Value': np.random.randn(100).cumsum() / 10 1})
df2['metric'] = 2
fig, ax1 = plt.subplots()
sns.set_style('white')
palette1 = 'Set2'
palette2 = 'Set1'
sns.violinplot(y=df1.Value, x=df1.modality, hue=df1.metric, palette=palette1, inner="stick", ax=ax1)
for violin in ax1.collections:
bbox = violin.get_paths()[0].get_extents()
x0, y0, width, height = bbox.bounds
violin.set_clip_path(plt.Rectangle((x0, y0), width / 2, height, transform=ax1.transData))
for line in ax1.lines:
x = line.get_xdata()
line.set_xdata([x[0], np.mean(x)])
ax1.set_ylabel("metric1")
ax1.set_xlabel("Modality")
ax2 = ax1.twinx()
sns.violinplot(y=df2.Value, x=df2.modality, hue=df2.metric, palette=palette2, inner="stick", ax=ax2)
ylim = ax2.get_ylim()
for violin in ax2.collections:
bbox = violin.get_paths()[0].get_extents()
x0, y0, width, height = bbox.bounds
violin.set_clip_path(plt.Rectangle((x0 width / 2, y0), width / 2, height, transform=ax2.transData))
for line in ax2.lines:
x = line.get_xdata()
line.set_xdata([np.mean(x), x[1]])
ax2.set_ylabel("Metric2")
ax2.set_xticklabels(ax2.get_xticklabels(), rotation=45, ha='right')
ax2.legend(handles=ax1.legend_.legendHandles ax2.legend_.legendHandles, title='Metric')
ax1.legend_.remove()
fig.tight_layout()
plt.show()
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/389335.html
標籤:Python matplotlib 海生 小提琴情节
上一篇:繪圖調整大小并保存為空
