Styling groupby boxplots
related #4264

The normal matplotlib boxplot command in Python returns a dictionary with keys for the boxes, median, whiskers, fliers, and caps. This makes styling really easy. Pandas.groupby boxplots, however, return an AxesSubplot object. This makes styling the plots more difficult.

I posted this question recently on [Stack Overflow](http://stackoverflow.com/questions/19453994/styling-of-pandas-groupby-boxplots) and eventually came to this solution. I hope it will be useful to others.

```
from numpy.random import rand
import matplotlib.pyplot as plt
import pandas as pd

#2 columns produces an array of 2 matplotlib.axes.AxesSubplot objects
df2 = pd.DataFrame(rand(10,2), columns=['Col1', 'Col2'] )
df2['X'] = pd.Series(['A','B','A','B','A','B','A','B','A','B'])

#1 column produces a single matplotlib.axes.AxesSubplot object
df1 = pd.DataFrame(rand(10), columns=['Col1'] )
df1['X'] = pd.Series(['A','B','A','B','A','B','A','B','A','B'])

def stylable_groupby_boxplot(df, by):
    '''
    If you plot only one column, boxplot returns a single AxesSubplot object.
    If there are several columns, boxplot returns an array of several AxesSubplot objects.
    '''
    bp = df.boxplot(by=by, grid=False)
    bptype = str(type(bp))
    if bptype == "<class 'matplotlib.axes.AxesSubplot'>":
        cl = bp.get_children()
        cl=[item for item in cl if isinstance(item, matplotlib.lines.Line2D)]
        bpdict = {}
        groups = df.groupby(by).groups.keys()
        for i in range(len(groups)):
            bpdict[groups[i]] = {'boxes': [], 'caps': [], 'fliers': [], 'medians': [], 'whiskers': []}
            bpdict[groups[i]]['boxes'] = [cl[4+8*i]]
            bpdict[groups[i]]['caps'] = [cl[2+8*i], cl[3+8*i]]
            bpdict[groups[i]]['fliers'] = [cl[6+8*i], cl[7+8*i]]
            bpdict[groups[i]]['medians'] = [cl[5+8*i]]
            bpdict[groups[i]]['whiskers'] = [cl[0+8*i], cl[1+8*i]]
    else:
        bpdict = {}
        groups = df.groupby(by).groups.keys()
        keys = range(len(bp))
        for i in keys:
            bpdict[keys[i]] = {}
            cl = bp[i].get_children()
            cl=[item for item in cl if isinstance(item, matplotlib.lines.Line2D)]
            for j in range(len(groups)):
                bpdict[keys[i]][groups[j]] = {'boxes': [], 'caps': [], 'fliers': [], 'medians': [], 'whiskers': []}
                bpdict[keys[i]][groups[j]]['boxes'] = [cl[4+8*j]]
                bpdict[keys[i]][groups[j]]['caps'] = [cl[2+8*j], cl[3+8*j]]
                bpdict[keys[i]][groups[j]]['fliers'] = [cl[6+8*j], cl[7+8*j]]
                bpdict[keys[i]][groups[j]]['medians'] = [cl[5+8*j]]
                bpdict[keys[i]][groups[j]]['whiskers'] = [cl[0+8*j], cl[1+8*j]]
    return bpdict

bp2 = stylable_groupby_boxplot(df2, by="X")
bp1 = stylable_groupby_boxplot(df1, by="X")


#2 column styling
plt.suptitle("")
plt.setp(bp2[0]['A']['boxes'], color='blue')
plt.setp(bp2[0]['A']['medians'], color='red')
plt.setp(bp2[0]['A']['whiskers'], color='blue')
plt.setp(bp2[0]['A']['fliers'], color='blue')
plt.setp(bp2[0]['A']['caps'], color='blue')
plt.setp(bp2[0]['B']['boxes'], color='red')
plt.setp(bp2[0]['B']['medians'], color='blue')
plt.setp(bp2[0]['B']['whiskers'], color='red')
plt.setp(bp2[0]['B']['fliers'], color='red')
plt.setp(bp2[0]['B']['caps'], color='red')
plt.setp(bp2[1]['A']['boxes'], color='green')
plt.setp(bp2[1]['A']['medians'], color='purple')
plt.setp(bp2[1]['A']['whiskers'], color='green')
plt.setp(bp2[1]['A']['fliers'], color='green')
plt.setp(bp2[1]['A']['caps'], color='green')
plt.setp(bp2[1]['B']['boxes'], color='purple')
plt.setp(bp2[1]['B']['medians'], color='green')
plt.setp(bp2[1]['B']['whiskers'], color='purple')
plt.setp(bp2[1]['B']['fliers'], color='purple')
plt.setp(bp2[1]['B']['caps'], color='purple')

#1 column styling
plt.suptitle("")
plt.setp(bp1['A']['boxes'], color='blue')
plt.setp(bp1['A']['medians'], color='red')
plt.setp(bp1['A']['whiskers'], color='blue')
plt.setp(bp1['A']['fliers'], color='blue')
plt.setp(bp1['A']['caps'], color='blue')
plt.setp(bp1['B']['boxes'], color='red')
plt.setp(bp1['B']['medians'], color='blue')
plt.setp(bp1['B']['whiskers'], color='red')
plt.setp(bp1['B']['fliers'], color='red')
plt.setp(bp1['B']['caps'], color='red')
```
