盒子图如何覆盖在Seaborn的群体图上?

时间:2017-06-18 13:59:50

标签: python matplotlib data-visualization seaborn boxplot

我正在尝试使用matplotlib和Seaborn绘制群体图和箱形图。我找到了如何将它们一起绘制,但是盒子图出现在swarm图下面。这个问题是群体图点淹没了箱形图并且箱形图丢失了。我认为通过切换所调用函数的顺序,让盒子图称为第一个而不是第二个,如下面的链接所示,会将盒子图覆盖在顶部,但它不会。

是否可以将箱形图覆盖在群体绘图点的顶部?如果没有,是否可以创建指示四分位数的线?

代码:

swarm_name = "Swarm_Plot_01"
#
sns.set_style("whitegrid")
ax = sns.boxplot(   data = [df.Rate_VL1R, df.Rate_V12R, df.Rate_V23R, df.Rate_VM3R ],
   showcaps=False,boxprops={'facecolor':'None'},
   showfliers=False,whiskerprops={'linewidth':0})
ax = sns.swarmplot( data = [df.Rate_VL1R, df.Rate_V12R, df.Rate_V23R, df.Rate_VM3R ] )
plt.show()
fig = ax.get_figure()
fig.savefig(swarm_name)
plt.figure()

这个问题与How to create a swarm plot with matplotlib有关,但并不完全相同,因为我希望改变风格,而不是将两者放在一起。

Swarm plot with box plot

3 个答案:

答案 0 :(得分:6)

问题在于箱图由许多不同的艺术家组成,而且由于采用了seaborn包装机制,我们不能简单地将整个箱图的zorder设置为更高的数字。

第一个天真的尝试是将swarmplot的zorder设置为零。虽然这将swarmplot点放在boxplot后面,但它也将它们放在网格线后面。因此,如果不使用网格线,则此解决方案仅是最佳的。

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()

enter image description here

如果需要网格线,我们可以将swarmplot的zorder设置为1,使其显示在网格线上方,并将boxplot的zorder设置为高数字。如上所述,这需要将zorder属性设置为其中的每个元素,因为zorder=10调用中的boxplot不会影响所有艺术家。相反,我们需要使用boxpropswhiskerprops参数来为这些参数设置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()

enter image description here

最终的解决方案,可以应用于艺术家属性根本没有访问权限的一般情况下,循环播放轴艺术家并为他们设置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()

enter image description here

答案 1 :(得分:5)

您需要更改zorder上的swarmplot

import seaborn.apionly as sns 
tips = sns.load_dataset("tips")
sns.boxplot("day", "tip", data=tips, boxprops={'facecolor':'None'})
sns.swarmplot("day", "tip", data=tips, zorder=.5)

enter image description here

答案 2 :(得分:0)

ImportanceOfBeingErnest的最后一个通用解决方案几乎对我有用(Python 3.5.4),除了中位数不可见。显然,彩色的箱形体的zorder隐藏了中位数。我的解决方案是将较低的zorder应用于补丁。

from matplotlib.patches import PathPatch

children2 = axarr[j].get_children()
for child in children2:
    if not child in children1:
        if isinstance(child, PathPatch):
            child.set_zorder(10)
        else:
            child.set_zorder(11)