2014-09-03 211 views
1

我試圖創建一個函數來計算數據框中多個變量的不同百分位數。我結合使用的字典用如下一個熊貓聚合函數:Percentiles加上Pandas groupby/aggregate

dfG = df.groupby('ClinicalEpisode') 
dfA = dfG.agg({ 'Total LOS' : 
       {'Total LOS P5' : 'pd.quantile(.05)', 
        'Total LOS P10' : 'pd.quantile(.10)', 
        'Total LOS P15' : 'pd.quantile(.15)', 
        'Total LOS P20' : 'pd.quantile(.20)', 
        'Total LOS P25' : 'pd.quantile(.25)', 
        'Total LOS P30' : 'pd.quantile(.30)', 
        'Total LOS P33' : 'pd.quantile(.333333)', 
        'Total LOS P35' : 'pd.quantile(.35)', 
        'Total LOS P40' : 'pd.quantile(.40)', 
        'Total LOS P50' : 'pd.quantile(.50)', 
        'Total LOS P75' : 'pd.quantile(.75)', 
        'Total LOS P80' : 'pd.quantile(.80)', 
        'Total LOS P90' : 'pd.quantile(.90)'}, 
      'Trigger SNF LOS' : 
       {'Trigger SNF LOS P5' : 'pd.quantile(.05)', 
        'Trigger SNF LOS P10' : 'pd.quantile(.10)', 
        'Trigger SNF LOS P15' : 'pd.quantile(.15)', 
        'Trigger SNF LOS P20' : 'pd.quantile(.20)', 
        'Trigger SNF LOS P25' : 'pd.quantile(.25)', 
        'Trigger SNF LOS P30' : 'pd.quantile(.30)', 
        'Trigger SNF LOS P33' : 'pd.quantile(.333333)', 
        'Trigger SNF LOS P35' : 'pd.quantile(.35)', 
        'Trigger SNF LOS P40' : 'pd.quantile(.40)', 
        'Trigger SNF LOS P50' : 'pd.quantile(.50)', 
        'Trigger SNF LOS P75' : 'pd.quantile(.75)', 
        'Trigger SNF LOS P80' : pd.quantile(.80), 
        'Trigger SNF LOS P90' : pd.quantile(.90)} 
      }) 

我已經嘗試了許多不同的功能,但似乎沒有任何與字典工作。

FWIW,我能夠計算這些位數一個變量一次處理這樣的代碼:

dfA = df.groupby('ClinicalEpisode')['Total LOS'].quantile(
    [.05, .1, .15, .2, .25, .3, .3333, .35, .4, .5, .6, .7, .75, .8, .9, .95]) 

不過,我真的希望能夠使用字典的方法。我只是卡住了。

回答

5

僅供參考,它有助於提供樣本數據和您的預期輸出。你應該比「我只是卡住」更明確。

你有兩個問題

  1. 沒有一個大熊貓quantile方法。有一個DataFrame.quantile方法,但我們不能使用它。這與你的第二個問題有關。
  2. GroupBy對象上的聚合方法需要帶一個數組並返回一個值的函數。我們將使用numpy的的percentile這需要一個數組和一個百分點,q,0和100之間。就像我說的,GROUPBY期待一個函數,只是需要一個數組,所以我們進行了修復使用functools.partial

以下是如何做到這一點:

In [62]: percentiles = [5, 10, 15, 20, 25, 30, 33, 35, 40, 50, 75, 80, 90] 

In [64]: from functools import partial 

In [65]: aggs = {'P {}'.format(q): partial(np.percentile, q=q) for q in percentiles} 
In [66]: aggs 
Out[66]: 
{'P 40': functools.partial(<function percentile at 0x10abde378>, q=40), 
'P 90': functools.partial(<function percentile at 0x10abde378>, q=90), 
...} 

現在我們可以通過aggs

In [71]: df = pd.DataFrame(np.random.randn(20, 4)) 

In [72]: df['g'] = np.random.randint(0, 2, 20) 

In [73]: df.groupby('g').agg({0: aggs, 1: aggs, 2:aggs}) 
Out[73]: 
      0                \ 
     P 40  P 90  P 80  P 20  P 30  P 35  P 75 
g                   
0 -1.451969 -0.134986 -0.466439 -1.726501 -1.475623 -1.463796 -0.632166 
1 0.249210 1.363307 1.029008 -0.644655 -0.241753 0.180993 0.952654 

                     1 \ 
     P 5  P 15  P 25 P 33  P 50  P 10  P 40 
g                   
0 -2.443653 -1.965552 -1.487451 -2.666927 -1.428315 -2.204603 -1.359988 
1 -1.423351 -0.728314 -0.491645 -1.507900 0.381779 -1.126839 0.261025 

.... 

如果您想擁有Total LOS ...,您可以修改詞典中的鍵。我只是有P [percentile],因爲它們來自的列位於MultiIndex的上層。

+0

Numpy現在支持[nanpercentile](https://docs.scipy.org/doc/numpy/reference/generated/numpy.nanpercentile.html),它跳過了'dropna'步驟。 – 2017-09-21 17:51:08