Set space between boxplots in Python Graphs generated nested box plots with Seaborn?

别来无恙 提交于 2019-11-28 00:53:24

问题


I am trying to set a space between the boxplots (between the green and orange boxes) created with Python Seaborn module's sns.boxplot(). Please see attached the graph, that the green and orange subplot boxes are stuck to each other, making it visually not the most appealing.

Can't find a way to do that, anyone could find a way (code attached)?

import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
tips = sns.load_dataset("tips")
sns.set(style="ticks", palette='Set2', font='Roboto Condensed')
sns.set_context("paper", font_scale=1.1, rc={"lines.linewidth": 1.1})
g=sns.factorplot(x="time", y="total_bill", hue="smoker",
               col="day", data=tips, kind="box", size=4, aspect=0.5,
                 width=0.8,fliersize=2.5,linewidth=1.1, notch=False,orient="v")
sns.despine(trim=True)
g.savefig('test6.png', format='png', dpi=600)

The Seaborn boxplot documentation is here: http://stanford.edu/~mwaskom/software/seaborn/generated/seaborn.boxplot.html


回答1:


Running the danger that this is not needed anymore, I found a solution to this problem. When drawing boxplots directly with matplotlib, the arrangement of the boxes can be controlled with the width and position keywords. However, when passing the positions keyword to sns.factorplot(kind='box',...), one gets a

TypeError: boxplot() got multiple values for keyword argument 'positions'

To get around this, one can set the widths of the boxes 'manually' after the boxplot has been created. This is a bit tedious, because the boxes are stored as PatchPatches within the individual Axes instances of the FacedGrid that is returned by sns.factorplot. Instead of the simple (x,y,width,height) syntax that Rects have, PathPatches use vertices to define the corners, which involves slightly more computation when one wants to adjust the boxes. On top of everything else, the PathPatches returned by matplotlib.boxplot contain an extra (ignored) vertex for the Path.CLOSEPOLY code, which is set to (0,0) and is best ignored. In addition to the box, the horizontal line that marks the median is now too wide and needs to be adjusted as well.

Below I define a function that adjusts widths of the boxes generated by the OP's example code(note the extra import):

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.flatten():

        ##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])

calling this function with

adjust_box_widths(g, 0.9)

gives the following output:



来源:https://stackoverflow.com/questions/31498850/set-space-between-boxplots-in-python-graphs-generated-nested-box-plots-with-seab

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!