如何在Seaborn箱线图中创建同一子组之间的间距?

9

我目前拥有一个Seaborn的箱线图,如下所示: 当前箱线图

每个x轴上的分组('hue')都相互接触。

此箱线图的代码如下:

bp_all = sns.boxplot(x='X_Values', y='Y_values', hue='Groups123', data=mydataframe, width=0.8, showfliers=False, linewidth=4.5, palette='coolwarm')

有没有办法在这三个组之间创建一个小空间,使它们不互相接触?

使用matplotlib箱线图,例如这里 - ImportanceOfBeingErnest
只需将您的绘图区域变宽,它就会自动调整。 - steven
@Steven,它没有起作用。 - VarunKumar
2个回答

13

我发现另一个用户发布的解决方案。此函数用于按您选择的因子调整所创建图形中所有对象的宽度。

from matplotlib.patches import PathPatch

def adjust_box_widths(g, fac):
    """
    Adjust the withs of a seaborn-generated boxplot.
    """

    # iterating through Axes instances
    for ax in g.axes:

        # iterating through axes artists:
        for c in ax.get_children():

            # searching for PathPatches
            if isinstance(c, PathPatch):
                # getting current width of box:
                p = c.get_path()
                verts = p.vertices
                verts_sub = verts[:-1]
                xmin = np.min(verts_sub[:, 0])
                xmax = np.max(verts_sub[:, 0])
                xmid = 0.5*(xmin+xmax)
                xhalf = 0.5*(xmax - xmin)

                # setting new width of box
                xmin_new = xmid-fac*xhalf
                xmax_new = xmid+fac*xhalf
                verts_sub[verts_sub[:, 0] == xmin, 0] = xmin_new
                verts_sub[verts_sub[:, 0] == xmax, 0] = xmax_new

                # setting new width of median line
                for l in ax.lines:
                    if np.all(l.get_xdata() == [xmin, xmax]):
                        l.set_xdata([xmin_new, xmax_new])
例如:
fig = plt.figure(figsize=(15, 13))
bp = sns.boxplot(#insert data and everything)
adjust_box_widths(fig, 0.9)

示例图


3
为使此方法适用于水平箱线图,需要进行哪些更改? - Tim Holdsworth

0

如果你想让这个适用于箱线图或盒形图,这里是答案。我已经使用了来自sns.catplot()的轴进行了测试。

def new_adjust_box_widths(axes, fac=0.9):
    """
    Adjust the widths of a seaborn-generated boxplot or boxenplot.
    
    Notes
    -----
    - thanks https://github.com/mwaskom/seaborn/issues/1076
    """
    from matplotlib.patches import PathPatch
    from matplotlib.collections import PatchCollection
    
    if isinstance(axes, list) is False:
        axes = [axes]
    
    # iterating through Axes instances
    for ax in axes:

        # iterating through axes artists:
        for c in ax.get_children():
            # searching for PathPatches
            if isinstance(c, PathPatch) or isinstance(c, PatchCollection):
                if isinstance(c, PathPatch):
                    p = c.get_path()
                else:
                    p = c.get_paths()[-1]
            
                # getting current width of box:
#                 p = c.get_path()
                verts = p.vertices
                verts_sub = verts[:-1]
                xmin = np.min(verts_sub[:, 0])
                xmax = np.max(verts_sub[:, 0])
                xmid = 0.5 * (xmin + xmax)
                xhalf = 0.5 * (xmax - xmin)

                # setting new width of box
                xmin_new = xmid - fac * xhalf
                xmax_new = xmid + fac * xhalf
                verts_sub[verts_sub[:, 0] == xmin, 0] = xmin_new
                verts_sub[verts_sub[:, 0] == xmax, 0] = xmax_new

                # setting new width of median line
                for l in ax.lines:
                    try:
                        if np.all(l.get_xdata() == [xmin, xmax]):
                            l.set_xdata([xmin_new, xmax_new])
                    except:
                        # /tmp/ipykernel_138835/916607433.py:32: DeprecationWarning: elementwise comparison failed;
                            # this will raise an error in the future.
                                # if np.all(l.get_xdata() == [xmin, xmax]):
                        pass
    pass

g = sns.catplot(*args, kind='box', **kwargs)  # or kind='boxen'

new_adjust_box_widths(list(g.axes[0]))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接