2013-10-18 55 views
2

Python中的正常matplotlib boxplot命令返回一個包含框,中位數,鬍鬚,傳單和大寫字母鍵的字典。這使得造型非常簡單。熊貓羣組的箱型造型

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') 

熊貓圖書館有一個「優化」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')函數產生的嗎?

+0

你能告訴我們一些示例代碼(用假數據?) – tacaswell

+0

我已經編輯了這個問題以包含示例數據和代碼,以及更清楚地展示我的問題。 –

回答

2

恐怕你必須硬編碼。就拿pandas例如:http://pandas.pydata.org/pandas-docs/stable/visualization.html#box-plotting

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') 

和劇情是這樣的:

enter image description here

每酒吧由8個項目組成。例如,第五項是中位數。第七和第八項可能是傳單,我們在這裏沒有。

瞭解了這些,修改了一些欄的部分很簡單。如果我們要設置的中位數爲2 linewidth

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

太棒了!非常有幫助@ ct-zhu。 我把你的解決方案,並創建一個函數,它需要一個熊貓數據框和你想groupby列並返回一個字典格式。我會把它放在他的答案下面,但它不適合。這是[github上的要點鏈接](https://gist.github.com/waltonjones/7065718)。 –

7

你也可以指定return_typedict。這將直接在字典中返回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]]