How to change the colour of the median line in seaborn boxplot?
More generally, how to change the colour values for a subset of the boxes properties in a seaborn boxplot? Be that the median, the whiskers, or such. I'm particularly interested in how to change the median value, as I have to create plots which have a dark colour and the median line can't be seen against it.
Here's some example code:
import matplotlib.pyplot as plt
import seaborn as sns
fig, ax1 = plt.subplots(figsize=(15,5)
colours = ["#000184", "#834177"]
sns.set_palette(sns.color_palette(colours))
tips = sns.load_dataset("tips")
sns.boxplot(x="day", y="total_bill", hue="smoker", data=tips, ax=ax1)
Which creates:
As can be seen, it's quite hard to see the median line against the blue here.
Note - I don't want to change the entire boxplot colour, just a subsection of the lines (in this case the median). Also - the option of changing it for a particular group (in this case the Yes
smokers) is needed, as the colour might not apply to both groups.
Solution 1:
It is possible to customize all artists in the boxplots, as demonstrated here. Since sns.boxplot()
forwards all **kwargs
to plt.boxplot()
, the following works:
tips = sns.load_dataset("tips")
colours = ["#000184", "#834177"]
sns.boxplot(x="day", y="total_bill", hue="smoker",
data=tips, palette=colours,
medianprops=dict(color="red", alpha=0.7),
flierprops=dict(markerfacecolor="#707070", marker="d"))
This way, one can modify the aesthetics of the box, the "fliers" (the points representing outliers), the median or mean line, and the whiskers/caps. See the docs of plt.boxplot()
for a complete list of modifiable properties.
Unfortunately, the above doesn't work to adjust the properties per category, as desired by the OP. But working with transparent colors (e.g. alpha=0.4
) can still lead to very satisfactory results.
Note: It would be great if seaborn exposed information about artists in a structured manner for such kind of modifications. While this is not possible with the current version (seaborn v0.11), the author of seaborn is considering to add this maybe in future, see here for instance.
Solution 2:
You can use medianprops
to change the color of the median line. However, there only will be one color for all boxplots. If you need to assign individual colors, you can loop through the generated lines.
ax1.get_lines()
gives a list of all Line2D
objects created by the boxplot
. There will be a Line2D
object for each of the elements that make up a box: 4 for the whiskers (2 vertical and 2 horizontal lines), 1 for the median and also 1 for the outliers (it is a Line2D
that shows markers without connecting lines). In case showmeans=True
there will also be a Line2D
with a marker for the mean. So in that case there would be 7 Line2D
s per box, in this case 6.
Note that a boxplot also accepts a parameter notch=True
which shows a confidence interval around the median. In the case of the current plot most of the confidence intervals are larger than the quartiles, which create some flipped notches. Depending on your real application, such notches can help to accentuate the median.
import matplotlib.pyplot as plt
import seaborn as sns
fig, ax1 = plt.subplots(figsize=(15,5))
colours = ["#000184", "#834177"]
sns.set_palette(sns.color_palette(colours))
tips = sns.load_dataset("tips")
sns.boxplot(x="day", y="total_bill", hue="smoker", data=tips, ax=ax1)
for line in ax1.get_lines()[4::12]:
line.set_color('orange')
for line in ax1.get_lines()[10::12]:
line.set_color('yellow')
plt.show()