I have created a nested boxplot with an overlayed stripplot using the Seaborn package. I have seen answers on stackoverflow regarding how to edit box properties both for individual boxes and for all boxes using ax.artists generated by sns.boxplot.
Is there any way to edit whisker, cap, flier, etc. properties using a similar method? Currently I have to manually edit values in the restyle_boxplot
method of the _BoxPlotter()
class in the seaborn -> categorical.py file to get from the default plot to the desired plot:
Default Plot:
Desired Plot:
Here is my code for reference:
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)
However, boxplot() can only set cap values of whiskers as the values of percentiles. e.g. Given my distribution is not a normal distribution, then the 95th/5th percentiles will not be the (mean+2std)/(mean-2std).
4, you can say: boxplots = ax. boxplot(myData, whis=[5, 95]) to set the whiskers at the 5th and 95th percentiles. Similarly, you'll be able to say boxplots = ax. boxplot(myData, whis=[0, 100]) to set the whiskers at the min and max.
fliers : points representing data that extend beyond the whiskers (fliers). means : points or lines representing the means.
Seaborn uses the boxplot() method to draw a boxplot. We can turn the boxplot into a horizontal boxplot by two methods first, we need to switch x and y attributes and pass it to the boxplot( ) method, and the other is to use the orient=”h” option and pass it to the boxplot() method.
You need to edit the Line2D
objects, which are stored in ax.lines
.
Heres a script to create a boxplot (based on the example here), and then edit the lines and artists to the style in your question (i.e. no fill, all the lines and markers the same colours, etc.)
You can also fix the rectangle patches in the legend, but you need to use ax.get_legend().get_patches()
for that.
I've also plotted the original boxplot on a second Axes, as a reference.
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()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With