1 回答

TA貢獻1799條經驗 獲得超8個贊
當前版本plt.boxplot()允許繪制這些元素中的大部分標準。showmeans如果設置為,將繪制均值True。它的屬性可以通過字典來控制meanprops。設置時patch_artist=True,將繪制一個填充框,而不僅僅是輪廓,boxprops控制它們的外觀。
要在頂部繪制散點圖,只需調用ax1.scatter. x 位置可以通過 隨機抖動i + np.random.uniform(-0.4, 0.4)。要強制它們位于箱線圖之上,可以更改它們的 z 順序。
由于傳單也是散點數據的一部分,因此將它們排除在外可能是有意義的 ( showfliers=False)。
要創建圖例,您可以收集所有所需元素的句柄并將它們傳遞給ax1.legend(). 請注意,您的箱線圖已經在 x 軸上獲得了標簽,因此將它們也放在圖例中可能有點多余。
import matplotlib.pyplot as plt
import numpy as np
random_dist_names = ['Overlap', 'Non overlap']
overlap = [6, 6, 5, 1, 3, 4, 4, 3]
non_overlap = [1, 2, 6, 6, 1, 3, 3, 3, 3, 3, 5, 2, 2]
data = [overlap, non_overlap]
fig, ax1 = plt.subplots(figsize=(6, 6))
fig.canvas.set_window_title('A Boxplot Example')
fig.subplots_adjust(left=0.075, right=0.95, top=0.9, bottom=0.25)
box_colors = ['darkkhaki', 'royalblue']
scatter_colors = ['purple', 'crimson']
legend_handles = []
for i, (values, box_color, scatter_color) in enumerate(zip(data, box_colors, scatter_colors), start=1):
bp = ax1.boxplot(values, positions=[i], showmeans=True, patch_artist=True, showfliers=False,
boxprops={'edgecolor': 'black', 'facecolor': box_color},
whiskerprops={'color': 'black'}, # flierprops={'color': 'red', 'marker': '+'},
medianprops={'color': 'lime', 'linewidth': 2, 'linestyle': ':'},
meanprops={'markerfacecolor': 'w', 'marker': '*', 'markeredgecolor': 'k', 'markersize': 10})
if i == 1:
legend_handles.append(bp['means'][0])
legend_handles.append(bp['boxes'][0])
ax1.scatter(i + np.random.uniform(-0.4, 0.4, len(values)), values, color=scatter_color, alpha=0.5, zorder=3)
ax1.yaxis.grid(True, linestyle='-', which='major', color='lightgrey', alpha=0.5)
ax1.set_axisbelow(True)
ax1.set_title('overlap and non_overlap against mRS')
ax1.set_xlim(0.5, len(data) + 0.5)
ax1.set_ylim(ymin=0)
ax1.set_xticklabels(random_dist_names, rotation=0, fontsize=8)
ax1.legend(legend_handles, ['Mean'] + random_dist_names, bbox_to_anchor=[1, -0.1], loc='upper right')
plt.show()
請注意,您的數據點很少,而且它們都有整數值,這使得紅點出現在水平線上。
PS:要創建與 Seaborn 類似的東西,數據的組織方式必須更類似于 pandas 數據框。這樣的數據框將有一列包含所有值,一列包含類別。
可以更自動地創建圖例。為了將均值也納入圖例,必須通過 將標簽分配給均值meanprops={..., 'label': 'Mean'}。不幸的是,這會為每個框創建一個圖例條目。這些可以通過首先獲取所有圖例條目并ax.get_legend_handles_labels()獲取句柄和標簽的子數組來跳過。
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
random_dist_names = ['Overlap', 'Non overlap']
overlap = [6, 6, 5, 1, 3, 4, 4, 3]
non_overlap = [1, 2, 6, 6, 1, 3, 3, 3, 3, 3, 5, 2, 2]
data_names = np.repeat(random_dist_names, [len(overlap), len(non_overlap)])
data_values = np.concatenate([overlap, non_overlap])
ax = sns.boxplot(x=data_names, y=data_values, hue=data_names, palette=['darkkhaki', 'royalblue'],
dodge=False, showfliers=False, showmeans=True,
meanprops={'markerfacecolor': 'w', 'marker': '*', 'markeredgecolor': 'k', 'markersize': 10, 'label': 'Mean'})
sns.stripplot(x=data_names, y=data_values, color='red', alpha=0.4)
handles, labels = ax.get_legend_handles_labels()
skip_pos = len(random_dist_names) - 1
ax.legend(handles[skip_pos:], labels[skip_pos:], bbox_to_anchor=(1.02, -0.05), loc='upper right')
plt.tight_layout()
plt.show()
添加回答
舉報