如何在Seaborn boxplot中编辑胡须,传单,帽子等属性

dsh*_*les 5 python matplotlib boxplot pandas seaborn

我使用Seaborn包创建了一个带有重叠stripplot的嵌套boxplot.我在stackoverflow上看到了关于如何使用sns.boxplot生成的ax.artists 为单个框所有框编辑属性的答案.

有没有办法用类似的方法编辑whisker,cap,flier等属性?目前我必须手动编辑seaborn - > categorical.py文件中类的restyle_boxplot方法中的值,_BoxPlotter()以从默认绘图到所需的绘图:

默认情节: 默认情节

期望的情节: 期望的情节

这是我的代码供参考:

sns.set_style('whitegrid')

fig1, ax1 = plt.subplots()


ax1 = sns.boxplot(x="Facility", y="% Savings", hue="Analysis",
             data=totalSavings)

plt.setp(ax1.artists,fill=False) # <--- Current Artist functionality

ax1 = sns.stripplot(x="Facility", y="% Savings", hue="Analysis",
                    data=totalSavings, jitter=.05,edgecolor = 'gray',
                    split=True,linewidth = 0, size = 6,alpha = .6)

ax1.tick_params(axis='both', labelsize=13)
ax1.set_xticklabels(['Test 1','Test 2','Test 3','Test 4','Test 5'], rotation=90)
ax1.set_xlabel('')
ax1.set_ylabel('Percent Savings (%)', fontsize = 14)


handles, labels = ax1.get_legend_handles_labels()
legend1 = plt.legend(handles[0:3], ['A','B','C'],bbox_to_anchor=(1.05, 1), 
                     loc=2, borderaxespad=0.)
plt.setp(plt.gca().get_legend().get_texts(), fontsize='12') 
fig1.set_size_inches(10,7)
Run Code Online (Sandbox Code Playgroud)

tmd*_*son 14

您需要编辑Line2D存储在其中的对象ax.lines.

下面是一个脚本来创建一个箱形图(基于这里的例子),然后根据你的问题中的样式编辑线条和艺术家(即没有填充,所有的线条和标记都是相同的颜色等)

您还可以修复图例中的矩形面片,但需要使用ax.get_legend().get_patches()它.

我还在第二个Axes上绘制了原始的boxplot作为参考.

import matplotlib.pyplot as plt
import seaborn as sns

fig,(ax1,ax2) = plt.subplots(2)

sns.set_style("whitegrid")
tips = sns.load_dataset("tips")

sns.boxplot(x="day", y="total_bill", hue="smoker", data=tips, palette="Set1", ax=ax1)
sns.boxplot(x="day", y="total_bill", hue="smoker", data=tips, palette="Set1", ax=ax2)

for i,artist in enumerate(ax2.artists):
    # Set the linecolor on the artist to the facecolor, and set the facecolor to None
    col = artist.get_facecolor()
    artist.set_edgecolor(col)
    artist.set_facecolor('None')

    # Each box has 6 associated Line2D objects (to make the whiskers, fliers, etc.)
    # Loop over them here, and use the same colour as above
    for j in range(i*6,i*6+6):
        line = ax2.lines[j]
        line.set_color(col)
        line.set_mfc(col)
        line.set_mec(col)

# Also fix the legend
for legpatch in ax2.get_legend().get_patches():
    col = legpatch.get_facecolor()
    legpatch.set_edgecolor(col)
    legpatch.set_facecolor('None')

plt.show()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • @Joe 是的,matplotlib v3.5 似乎发生了一些变化。请参阅 JohanC 的回答以获取最新版本 (3认同)

Joh*_*anC 9

对于 matplotlib 3.5,盒子的矩形不再存储在 中ax2.artists,而是存储在ax2.patches. 由于子图的背景也存储为矩形补丁,因此需要过滤补丁列表。

下面的代码进一步做了一些调整:

  • 属于一个箱线图的确切行数会被计算在内,因为根据箱线图选项,可能会有不同的行数
  • saturation=1用来; Seaborn 更喜欢对较大区域添加一些去饱和度,但完全饱和时线条会更明显
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns

fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(12, 5))

sns.set_style("whitegrid")
tips = sns.load_dataset("tips")

sns.boxplot(x="day", y="total_bill", hue="smoker", data=tips, palette="Set1", ax=ax1)
sns.boxplot(x="day", y="total_bill", hue="smoker", data=tips, palette="Set1", saturation=1, ax=ax2)

box_patches = [patch for patch in ax2.patches if type(patch) == matplotlib.patches.PathPatch]
if len(box_patches) == 0:  # in matplotlib older than 3.5, the boxes are stored in ax2.artists
    box_patches = ax2.artists
num_patches = len(box_patches)
lines_per_boxplot = len(ax2.lines) // num_patches
for i, patch in enumerate(box_patches):
    # Set the linecolor on the patch to the facecolor, and set the facecolor to None
    col = patch.get_facecolor()
    patch.set_edgecolor(col)
    patch.set_facecolor('None')

    # Each box has associated Line2D objects (to make the whiskers, fliers, etc.)
    # Loop over them here, and use the same color as above
    for line in ax2.lines[i * lines_per_boxplot: (i + 1) * lines_per_boxplot]:
        line.set_color(col)
        line.set_mfc(col)  # facecolor of fliers
        line.set_mec(col)  # edgecolor of fliers

# Also fix the legend
for legpatch in ax2.legend_.get_patches():
    col = legpatch.get_facecolor()
    legpatch.set_edgecolor(col)
    legpatch.set_facecolor('None')
sns.despine(left=True)
plt.show()
Run Code Online (Sandbox Code Playgroud)

sns.boxplot 带线