Укладка Pandas для групповых боксов

Обычная команда matplotlib boxplot в Python возвращает словарь с ключами для блоков, медианы, усов, листовки и заглавных букв. Это делает укладку действительно легкой.

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

# Create a dataframe and subset it for a boxplot
df1 = pd.DataFrame(rand(10), columns=['Col1'] )
df1['X'] = pd.Series(['A','B','A','B','A','B','A','B','A','B'])
boxes= [df1[df1['X'] == 'A'].Col1, df1[df1['X'] == 'B'].Col1]

# Call the standard matplotlib boxplot function,
# which returns a dictionary including the parts of the graph
mbp = plt.boxplot(boxes)
print(type(mbp))

# This dictionary output makes styling the boxplot easy
plt.setp(mbp['boxes'], color='blue')
plt.setp(mbp['medians'], color='red')
plt.setp(mbp['whiskers'], color='blue')
plt.setp(mbp['fliers'], color='blue')

Библиотека Pandas имеет "оптимизированную" функцию boxplot для своих сгруппированных (иерархически проиндексированных) фреймов данных. Однако вместо того, чтобы возвращать несколько словарей для каждой группы, он возвращает объект matplotlib.axes.AxesSubplot. Это делает укладку очень сложной.

# Pandas has a built-in boxplot function that returns
# a matplotlib.axes.AxesSubplot object
pbp = df1.boxplot(by='X')
print(type(pbp))

# Similar attempts at styling obviously return TypeErrors
plt.setp(pbp['boxes'], color='blue')
plt.setp(pbp['medians'], color='red')
plt.setp(pbp['whiskers'], color='blue')
plt.setp(pbp['fliers'], color='blue')

Доступен ли этот объект AxisSubplot, созданный функцией pandas df.boxplot(by='X')?

2 ответа

Решение

Боюсь, у вас есть жесткий код. Возьмите pandas пример: http://pandas.pydata.org/pandas-docs/stable/visualization.html

from pandas import *
import matplotlib
from numpy.random import rand
import matplotlib.pyplot as plt
df = DataFrame(rand(10,2), columns=['Col1', 'Col2'] )
df['X'] = Series(['A','A','A','A','A','B','B','B','B','B'])
bp = df.boxplot(by='X')
cl=bp[0].get_children()
cl=[item for item in cl if isinstance(item, matplotlib.lines.Line2D)]

Теперь давайте определим, какие из них - коробки, медианы и т. Д.

for i, item in enumerate(cl):
    if item.get_xdata().mean()>0:
        bp[0].text(item.get_xdata().mean(), item.get_ydata().mean(), str(i), va='center', ha='center')

И сюжет выглядит так:

введите описание изображения здесь

Каждый бар состоит из 8 предметов. например, 5-й пункт является медианой. Седьмой и восьмой пункты - это, вероятно, листовки, которых у нас здесь нет.

Зная это, изменить некоторую часть панели легко. Если мы хотим установить медиану, чтобы иметь linewidth из 2:

for i in range(_your_number_of_classes_2_in_this_case):
    cl[5+i*8].set_linewidth(2.)

Вы также можете указать return_type как dict, Это вернет свойства boxplot непосредственно в словаре, который индексируется каждым столбцом, который был нанесен в boxplot.

Чтобы использовать пример выше (в IPython):

from pandas import *
import matplotlib
from numpy.random import rand
import matplotlib.pyplot as plt
df = DataFrame(rand(10,2), columns=['Col1', 'Col2'] )
df['X'] = Series(['A','A','A','A','A','B','B','B','B','B'])
bp = df.boxplot( by='X', return_type='dict' )

>>> bp.keys()
['Col1', 'Col2']

>>> bp['Col1'].keys()
['boxes', 'fliers', 'medians', 'means', 'whiskers', 'caps']

Теперь, изменение ширины линий - вопрос понимания списка:

>>> [ [item.set_linewidth( 2 ) for item in bp[key]['medians']] for key in bp.keys() ]
[[None, None], [None, None]]
Другие вопросы по тегам