如何在 Seaborn boxplot 中编辑胡须、传单、帽等的属性
How to edit properties of whiskers, fliers, caps, etc. in Seaborn boxplot
我使用 Seaborn 包创建了一个嵌套箱线图和一个重叠的条带图。我在 Whosebug 上看到了关于如何使用 [=31 生成的 ax.artists 为 and for 编辑 box 属性的答案=].
有没有什么方法可以使用类似的方法来编辑晶须、帽盖、传单等属性?目前,我必须手动编辑 seaborn -> categorical.py 文件中 _BoxPlotter()
class 的 restyle_boxplot
方法中的值,以从默认绘图获取所需的绘图:
默认剧情:
想要的情节:
这是我的代码供参考:
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)
您需要编辑存储在 ax.lines
中的 Line2D
个对象。
这是一个创建箱形图的脚本(基于示例 here),然后将线条和艺术家编辑为您问题中的样式(即无填充,所有线条和标记颜色相同等)
你也可以修复图例中的矩形补丁,但你需要使用ax.get_legend().get_patches()
。
我还在第二个坐标轴上绘制了原始箱线图,作为参考。
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()
对于 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()
我使用 Seaborn 包创建了一个嵌套箱线图和一个重叠的条带图。我在 Whosebug 上看到了关于如何使用 [=31 生成的 ax.artists 为
有没有什么方法可以使用类似的方法来编辑晶须、帽盖、传单等属性?目前,我必须手动编辑 seaborn -> categorical.py 文件中 _BoxPlotter()
class 的 restyle_boxplot
方法中的值,以从默认绘图获取所需的绘图:
默认剧情:
想要的情节:
这是我的代码供参考:
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)
您需要编辑存储在 ax.lines
中的 Line2D
个对象。
这是一个创建箱形图的脚本(基于示例 here),然后将线条和艺术家编辑为您问题中的样式(即无填充,所有线条和标记颜色相同等)
你也可以修复图例中的矩形补丁,但你需要使用ax.get_legend().get_patches()
。
我还在第二个坐标轴上绘制了原始箱线图,作为参考。
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()
对于 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()