3

I followed the examples on this link on how to create a boxplot with colors. I have been trying different ways to separate these boxplots on two different positions instead of both of them overlapping but to no avail. If I specify different positions for both of them, they stay on the bp2 position. How do I put these two boxplots side by side?

import matplotlib.pyplot as plt

def color_boxplot(data, color):
   bp = boxplot(data, patch_artist=True,  showmeans=True)
   for item in ['boxes', 'whiskers', 'fliers', 'medians', 'caps']:
        plt.setp(bp[item], color=color)


data1 = [1, 2, 3, 4, 5]
data2 = [4, 5, 6, 7, 8]
fig, ax = plt.subplots()
bp1 = color_boxplot(data1, 'green')
bp2 = color_boxplot(data2, 'red')
plt.show()

EDIT: Added sample data.

enter image description here

Gabriele
  • 737
  • 2
  • 8
  • 20

3 Answers3

4

What about using a pre-made boxplot from seaborn?

import seaborn as sns
sns.boxplot(data=[data1, data2])

If you want to choose the colors manually you can use the xkcd color list:

sns.boxplot(
    data=[data1, data2],
    palette=[sns.xkcd_rgb["pale red"], sns.xkcd_rgb["medium green"]],
    showmeans=True,
)

enter image description here

Sasha Tsukanov
  • 1,025
  • 9
  • 20
  • Is it going to be easier to color those boxplots using seaborn? Thats the only reason why I have been struggling so much. – Gabriele Sep 27 '18 at 11:44
  • @Gabriele The two boxplots are colored differently by default. Do you need to manually choose the colors? – Sasha Tsukanov Sep 27 '18 at 11:46
  • Quick google search doesnt tell me how to show the mean in each boxplot using seaborn. Its not the same as showmeans=True in matplotlib. – Gabriele Sep 27 '18 at 11:59
  • I am not a smart person. Thanks, Sasha! – Gabriele Sep 27 '18 at 12:06
  • @Gabriele in general you can expect that arguments valid for matplotlib are valid for analogous plot functions in seaborn. They are just marked as `**kwargs` in seaborn documentation – Sasha Tsukanov Sep 27 '18 at 12:09
4

Although I do think Sasha's answer is probably the best choice given the circumstance, if you really want to keep the appearance of your original post, you have to modify your code so that you are using only one call to boxplot. That way, matplotlib takes care of positioning them correctly on the axes. You can then iterate over the dictionary returned by by boxplot to adjust the output

data1 = [1, 2, 3, 4, 5]
data2 = [4, 5, 6, 7, 8]
data3 = [0, 1, 2]
data = [data1,data2, data3]
colors = ['red','green','blue']
fig, ax = plt.subplots()
box_dict = ax.boxplot(data, patch_artist=True,  showmeans=True)
for item in ['boxes', 'fliers', 'medians', 'means']:
    for sub_item,color in zip(box_dict[item], colors):
        plt.setp(sub_item, color=color)
# whiskers and caps have to be treated separately since there are two of each for each plot
for item in ['whiskers', 'caps']:
    for sub_items,color in zip(zip(box_dict[item][::2],box_dict[item][1::2]),colors):
        plt.setp(sub_items, color=color)

enter image description here

Diziet Asahi
  • 38,379
  • 7
  • 60
  • 75
3

To keep your code mostly intact, you can just add another argument for the position to your function.

import matplotlib.pyplot as plt

def color_boxplot(data, color, pos=[0], ax=None):
    ax = ax or plt.gca()
    bp = ax.boxplot(data, patch_artist=True,  showmeans=True, positions=pos)
    for item in ['boxes', 'whiskers', 'fliers', 'medians', 'caps']:
        plt.setp(bp[item], color=color)


data1 = [1, 2, 3, 4, 5]
data2 = [4, 5, 6, 7, 8]
fig, ax = plt.subplots()
bp1 = color_boxplot(data1, 'green', [1])
bp2 = color_boxplot(data2, 'red', [2])
ax.autoscale()
ax.set(xticks=[1,2], xticklabels=[1,2])
plt.show()

enter image description here

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712