1

I'm tring my best to draw a grouped boxplot similar to the following. There is no filling in the box and different types of whisker&edge have different colors:

Target.png

Sample code:

  • generate dataframe for boxplot
x, y, category = list(), list(), list()
for i in range(5):
    for j in range(10):
        for k in ['Yes', 'No']:
            x.append(i)
            y.append(np.random.rand(1)[0])
            category.append(k)

df_for_boxplot = pd.DataFrame({
    'X': x,
    'Y': y,
    'category': category
})
  • box plot with seaborn
sns.set_theme(style="ticks", palette="pastel")
ax = sns.boxplot(x="X", y="Y", data=df_for_boxplot,
                 hue="category", 
                 # boxprops={"edgecolor": "r"}, # This makes all edges turn blue but I wanna set different catograys in different color.
                 palette=['w','w'],
                 whiskerprops={'linestyle':'--'}, showcaps = False)

# Select some boxes in particular by indexing ax.artists and set the edgecolor
[ax.artists[i].set_edgecolor('r') for i in [0,2,4,6,8]]
[ax.artists[i].set_edgecolor('b') for i in [1,3,5,7,9]]

# I can also change the color of specific line but it can only be set artificially.:
ax.lines[0].set_color('r')

ax.legend(loc='upper left')

I can only manually set the color of edge and whisker by indexing ax.artists and ax.lines because I don't know how to uniformly set different categories of boxes. It is difficult to set it manually when there are too many boxes in the image or the data is too complicated.

Is there a more efficient solution? Any suggestions would be appreciated!

(I'm sorry about can't post images because I'm new here and my poor English)

DelinQu
  • 11
  • 2

1 Answers1

0

The excellent answer here did not solve the problem.

I did some research and changed the box, fill, and other lines from ax.Patches to PathPatch only, and I'm waiting for advice from someone more skilled in this kind of thing as to why it can't be addressed in ax.artists.

fig, ax = plt.subplots(figsize=(12,9))

#sns.set_theme(style="ticks", palette="pastel")
sns.boxplot(x="X", y="Y",
            data=df_for_boxplot,
            hue="category", 
            # boxprops={"edgecolor": "r"}, 
            # palette=['w','w'],
            whiskerprops={'linestyle':'--'},
            # showcaps=False,
            ax=ax
                )

p = 0
for box in ax.patches:
    #print(box.__class__.__name__)
    if box.__class__.__name__ == 'PathPatch':
        if p % 2 == 0:
            box.set_edgecolor('C1')
            box.set_facecolor('white')
            for k in range(6*p,6*(p+1)):
                ax.lines[k].set_color('C1')
            p += 1
        else:
            box.set_edgecolor('C0')
            box.set_facecolor('white')
            for k in range(6*p,6*(p+1)):
                ax.lines[k].set_color('C0')
            p +=1

for legpatch in ax.get_legend().get_patches():
    col = legpatch.get_facecolor()
    legpatch.set_edgecolor(col)
    legpatch.set_facecolor('None')
        
plt.show()

enter image description here

r-beginners
  • 31,170
  • 3
  • 14
  • 32