'Change the facecolor of boxplot in pandas

I need to change the colors of the boxplot drawn using pandas utility function. I can change most properties using the color argument but can't figure out how to change the facecolor of the box. Someone knows how to do it?

import pandas as pd
import numpy as np
data = np.random.randn(100, 4)
labels = list("ABCD")
df = pd.DataFrame(data, columns=labels)
props = dict(boxes="DarkGreen", whiskers="DarkOrange", medians="DarkBlue", caps="Gray")
df.plot.box(color=props)


Solution 1:[1]

While I still recommend seaborn and raw matplotlib over the plotting interface in pandas, it turns out that you can pass patch_artist=True as a kwarg to df.plot.box, which will pass it as a kwarg to df.plot, which will pass is as a kwarg to matplotlib.Axes.boxplot.

import pandas as pd
import numpy as np
data = np.random.randn(100, 4)
labels = list("ABCD")
df = pd.DataFrame(data, columns=labels)
props = dict(boxes="DarkGreen", whiskers="DarkOrange", medians="DarkBlue", caps="Gray")
df.plot.box(color=props, patch_artist=True)

enter image description here

Solution 2:[2]

As suggested, I ended up creating a function to plot this, using raw matplotlib.

def plot_boxplot(data, ax):
    bp = ax.boxplot(data.values, patch_artist=True)

    for box in bp['boxes']:
        box.set(color='DarkGreen')
        box.set(facecolor='DarkGreen')

    for whisker in bp['whiskers']:
        whisker.set(color="DarkOrange")

    for cap in bp['caps']:
        cap.set(color="Gray")

    for median in bp['medians']:
        median.set(color="white")

    ax.axhline(0, color="DarkBlue", linestyle=":")

    ax.set_xticklabels(data.columns)

Solution 3:[3]

I suggest using df.plot.box with patch_artist=True and return_type='both' (which returns the matplotlib axes the boxplot is drawn on and a dictionary whose values are the matplotlib Lines of the boxplot) in order to have the best customization possibilities.

For example, given this data:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame(
    data=np.random.randn(100, 4), 
    columns=list("ABCD")
)

you can set a specific color for all the boxes:

fig,ax = plt.subplots(figsize=(9,6)) 
ax,props = df.plot.box(patch_artist=True, return_type='both', ax=ax)
for patch in props['boxes']:
    patch.set_facecolor('lime')
plt.show()

enter image description here

you can set a specific color for each box:

colors = ['green','blue','yellow','red']

fig,ax = plt.subplots(figsize=(9,6)) 
ax,props = df.plot.box(patch_artist=True, return_type='both', ax=ax)
for patch,color in zip(props['boxes'],colors):
    patch.set_facecolor(color)
plt.show()

enter image description here

you can easily integrate a colormap:

colors = np.random.randint(0,10, 4)
cm = plt.cm.get_cmap('rainbow')
colors_cm = [cm((c-colors.min())/(colors.max()-colors.min())) for c in colors]

fig,ax = plt.subplots(figsize=(9,6)) 
ax,props = df.plot.box(patch_artist=True, return_type='both', ax=ax)
for patch,color in zip(props['boxes'],colors_cm):
    patch.set_facecolor(color)
# to add colorbar
fig.colorbar(plt.cm.ScalarMappable(
    plt.cm.colors.Normalize(min(colors),max(colors)), 
    cmap='rainbow'
), ax=ax, cmap='rainbow')
plt.show()

enter image description here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Paul H
Solution 2 Kapil Sharma
Solution 3 Marco Cerliani