0

I would like to superimpose a hatched boxplot on another one. On the right figure, I get almost what I want with the shown code except the caps and median are not the same colors as the "walls" of the boxplot.

If I activate the first exit() (left figure), and then the second (middle figure), I realize matplotlib was not really designed to superimpose boxplots. Would there be a way to get what I want ?

enter image description here

Code excerpted from this answer

import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns

fig, ax = plt.subplots(figsize=(2, 5))

tips = sns.load_dataset("tips")
tips['total_bill_plus5'] = tips['total_bill'] + 5

sns.boxplot(x="day", y="total_bill", hue="smoker", data=tips, fliersize=0, whis=0)
plt.ylim(0, 50)
#exit()
sns.boxplot(x="day", y="total_bill_plus5", hue="smoker", data=tips, fliersize=0, whis=0)
#exit()
ax.get_legend().remove()

box_patches = [patch for patch in ax.patches if type(patch) == matplotlib.patches.PathPatch]
if len(box_patches) == 0:  # in matplotlib older than 3.5, the boxes are stored in ax.artists
    box_patches = ax.artists

num_patches = len(box_patches)
lines_per_boxplot = len(ax.lines) // num_patches
col = (.5, .5, .5, 1)

for i, patch in enumerate( box_patches[int(num_patches/2):] ):
    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 ax.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
        patch.set_hatch('////')

Sorry I don't think it's a duplicate since I see no overlay of boxplots on How to add hatches to boxplots with sns.boxplot or sns.catplot

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
PierreL
  • 169
  • 9
  • 1
    I don't think you tried the code in the duplicate, because it only requires removing `patch.set_facecolor('none')`, and setting `patch.set_edgecolor('k')` instead of to `fc`. See [code and plot](https://i.stack.imgur.com/wIpO7.png) – Trenton McKinney Jun 28 '22 at 16:12
  • @PierreL You could add `saturation=1` in the second call to `sns.boxplot`: `sns.boxplot(x="day", y="total_bill_plus5", ...., saturation=1)` to get brighter colors. Note that for a post to be a duplicate, it isn't needed to be a 100% duplicate, as long as the relevant information solves your new problem. Could you elaborate a bit further what you need to be different? – JohanC Jun 28 '22 at 22:49
  • 1
    Note that in your `for i, patch in enumerate( box_patches[int(num_patches/2):] ):` the variable `patch` goes through the second half of the list while the variable `i` just goes `0,1,2,...`. You might want to rewrite this as `for i, patch in enumerate(box_patches):` followed by `if i >= num_patches//2:`. Or, alternatively, write it as `for i, patch in enumerate(box_patches[num_patches//2:], start=num_patches//2 ):`. – JohanC Jun 28 '22 at 22:49
  • 1
    Which results in [code & plot](https://i.stack.imgur.com/xfdWf.png) – Trenton McKinney Jun 28 '22 at 22:52
  • Great it works. Thank you very much. I thought matplotlib couldnt handle the overlay since I saw it nowhere else while it was my stupid mistake. – PierreL Jun 29 '22 at 17:21

0 Answers0