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()
添加回答
举报