问题是箱线图由许多不同的艺术家组成,并且由于 seaborn 包装机制,我们不能简单地将完整箱线图的 zorder 设置为更高的数字。
第一次天真的尝试是将 swarmplot 的 zorder 设置为零。虽然这将 swarmplot 点放在箱线图后面,但它也将它们放在网格线后面。因此,只有在不使用网格线的情况下,该解决方案才是最优的。
import seaborn as sns
import matplotlib.pyplot as plt
tips = sns.load_dataset("tips")
# plot swarmplot
ax = sns.swarmplot(x="day", y="total_bill", data=tips, zorder=0)
# plot boxplot
sns.boxplot(x="day", y="total_bill", data=tips,
showcaps=False,boxprops={'facecolor':'None'},
showfliers=False,whiskerprops={'linewidth':0}, ax=ax)
plt.show()
如果需要网格线,我们可以将 swarmplot 的 zorder 设置为 1,使其显示在网格线上方,并将箱线图的 zorder 设置为较高的数字。如上所述,这需要将 zorder 属性设置为它的每个元素,因为 zorder=10 在 boxplot 调用中不会影响所有艺术家。相反,我们需要使用 boxprops、whiskerprops 参数来设置这些参数的 zorder 属性。
import seaborn as sns
import matplotlib.pyplot as plt
tips = sns.load_dataset("tips")
# plot swarmplot
ax = sns.swarmplot(x="day", y="total_bill", data=tips, zorder=1)
# plot boxplot
sns.boxplot(x="day", y="total_bill", data=tips,
showcaps=False,boxprops={'facecolor':'None', "zorder":10},
showfliers=False,whiskerprops={'linewidth':0, "zorder":10},
ax=ax, zorder=10)
plt.show()
最终的解决方案,可以应用于根本无法访问艺术家属性的一般情况,是遍历轴艺术家并根据他们是否属于一个或另一个情节为他们设置 zorder。
import seaborn as sns
import matplotlib.pyplot as plt
tips = sns.load_dataset("tips")
# plot swarmplot
ax = sns.swarmplot(x="day", y="total_bill", data=tips)
#get all children of axes
children1 = ax.get_children()
# plot boxplot
sns.boxplot(x="day", y="total_bill", data=tips,
showcaps=False,boxprops={'facecolor':'None'},
showfliers=False,whiskerprops={'linewidth':0}, ax=ax)
# again, get all children of axes.
children2 = ax.get_children()
# now those children which are in children2 but not in children1
# must be part of the boxplot. Set zorder high for those.
for child in children2:
if not child in children1:
child.set_zorder(10)
plt.show()