如何使用 sns.boxplot 或 sns.catplot 添加剖面线到箱线图

Nar*_*ini 4 python data-visualization boxplot seaborn catplot

我需要向分类箱线图添加剖面线。我所拥有的是这样的: 在此输入图像描述

我需要的是这样的(带有中线):

在此输入图像描述

我尝试过的是这段代码:

exercise = sns.load_dataset("exercise")
g = sns.catplot(x="time", y="pulse", hue="kind", data=exercise, kind="box")
bars = g.axes[0][0].patches
hatches=['//','..','xx','//','..','xx','//','..','xx']
for pat,bar in zip(hatches,bars):
    bar.set_hatch(pat)
Run Code Online (Sandbox Code Playgroud)

这只会生成第一个数字。第3-6行的想法来自这个问题。但进入第 3 行的想法axes[0][0]来自于这个问题

因为 FacetGrid 没有补丁或容器等属性,所以很难将单个图中的影线答案适应分类图,所以我无法弄清楚。

其他无效的审查问题:

Tre*_*ney 6

  1. 使用 迭代每个子图/FacetGrid for ax in g.axes.flat:
  2. ax.patches包含matplotlib.patches.Rectanglematplotlib.patches.PathPatch,因此必须使用正确的。
  • 注意:每个 Facet 中的每个组都必须出现所有色调,否则patcheshatches将不匹配。
    • 在这种情况下,可能需要手动或条件代码来正确确定h,因此zip(patches, h)有效。
  • 测试于python 3.10, pandas 1.4.2, matplotlib 3.5.1,seaborn 0.11.2
import matplotlib as mpl
import seaborn as sns

# load test data
exercise = sns.load_dataset("exercise")

# plot
g = sns.catplot(x="time", y="pulse", hue="kind", data=exercise, col='diet', kind="box")

# hatches must equal the number of hues (3 in this case)
hatches = ['//', '..', 'xx']

# iterate through each subplot / Facet
for ax in g.axes.flat:

    # select the correct patches
    patches = [patch for patch in ax.patches if type(patch) == mpl.patches.PathPatch]
    # the number of patches should be evenly divisible by the number of hatches
    h = hatches * (len(patches) // len(hatches))
    # iterate through the patches for each subplot
    for patch, hatch in zip(patches, h):
        patch.set_hatch(hatch)
        fc = patch.get_facecolor()
        patch.set_edgecolor(fc)
        patch.set_facecolor('none')
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 添加以下内容以更改图例。
for lp, hatch in zip(g.legend.get_patches(), hatches):
    lp.set_hatch(hatch)
    fc = lp.get_facecolor()
    lp.set_edgecolor(fc)
    lp.set_facecolor('none')
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


  • 如果仅使用axes-level sns.boxplot,则无需迭代多个轴。
ax = sns.boxplot(x="time", y="pulse", hue="kind", data=exercise)

# select the correct patches
patches = [patch for patch in ax.patches if type(patch) == mpl.patches.PathPatch]
# the number of patches should be evenly divisible by the number of hatches
h = hatches * (len(patches) // len(hatches))
# iterate through the patches for each subplot
for patch, hatch in zip(patches, h):
    patch.set_hatch(hatch)
    fc = patch.get_facecolor()
    patch.set_edgecolor(fc)
    patch.set_facecolor('none')

l = ax.legend()
    
for lp, hatch in zip(l.get_patches(), hatches):
    lp.set_hatch(hatch)
    fc = lp.get_facecolor()
    lp.set_edgecolor(fc)
    lp.set_facecolor('none')
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


  • 要保持箱线图的面色:
    1. 消除patch.set_facecolor('none')
    2. 将边缘颜色设置为'k'(黑色)而不是fc, patch.set_edgecolor('k')
    • 也适用于sns.catplot代码。
ax = sns.boxplot(x="time", y="pulse", hue="kind", data=exercise)

# select the correct patches
patches = [patch for patch in ax.patches if type(patch) == mpl.patches.PathPatch]
# the number of patches should be evenly divisible by the number of hatches
h = hatches * (len(patches) // len(hatches))
# iterate through the patches for each subplot
for patch, hatch in zip(patches, h):
    patch.set_hatch(hatch)
    patch.set_edgecolor('k')
    
l = ax.legend()
    
for lp, hatch in zip(l.get_patches(), hatches):
    lp.set_hatch(hatch)
    lp.set_edgecolor('k')
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述