2013-01-12 16 views
10

Ho un dataframe con colonne numeriche. Per ogni colonna vorrei calcolare le informazioni quantili e assegnare ciascuna riga a una di esse. Ho provato a utilizzare lo qcut() method per restituire un elenco di contenitori, ma ho finito per calcolare singolarmente i raccoglitori. Quello che pensavo potesse esistere ma non riuscivo a trovare sarebbe un metodo come df.to_quintile(num of quantiles). Questo è quello che mi è venuto in mente, ma mi chiedo se ci sia un modo più succinto/panda per farlo.Converti dati nel cestino quantile

import pandas as pd 

#create a dataframe 
df = pd.DataFrame(randn(10, 4), columns=['A', 'B', 'C', 'D']) 

def quintile(df, column): 
    """ 
    calculate quintiles and assign each sample/column to a quintile 
    """ 
    #calculate the quintiles using pandas .quantile() here 
    quintiles = [df[column].quantile(value) for value in [0.0,0.2,0.4,0.6,0.8]] 
    quintiles.reverse() #reversing makes the next loop simpler 

    #function to check membership in quintile to be used with pandas apply 
    def check_quintile(x, quintiles=quintiles): 
     for num,level in enumerate(quintiles): 
      #print number, level, level[1] 
      if x >= level: 
       print x, num 
       return num+1 

    df[column] = df[column].apply(check_quintile) 

quintile(df,'A') 

grazie, Zach CP

EDIT: Dopo aver visto DSM rispondono alla funzione può essere scritta molto più semplice (in basso). Uomo, questo è dolce.

def quantile(column, quantile=5): 
    q = qcut(column, quantile) 
    return len(q.levels)- q.labels 
df.apply(quantile) 
#or 
df['A'].apply(quantile) 

risposta

13

Penso utilizzando il labels memorizzato all'interno dell'oggetto Categorical restituito da qcut può rendere questo molto più semplice. Per esempio:

>>> import pandas as pd 
>>> import numpy as np 
>>> np.random.seed(1001) 
>>> df = pd.DataFrame(np.random.randn(10, 2), columns=['A', 'B']) 
>>> df 
      A   B 
0 -1.086446 -0.896065 
1 -0.306299 -1.339934 
2 -1.206586 -0.641727 
3 1.307946 1.845460 
4 0.829115 -0.023299 
5 -0.208564 -0.916620 
6 -1.074743 -0.086143 
7 1.175839 -1.635092 
8 1.228194 1.076386 
9 0.394773 -0.387701 
>>> q = pd.qcut(df["A"], 5) 
>>> q 
Categorical: A 
array([[-1.207, -1.0771], (-1.0771, -0.248], [-1.207, -1.0771], 
     (1.186, 1.308], (0.569, 1.186], (-0.248, 0.569], (-1.0771, -0.248], 
     (0.569, 1.186], (1.186, 1.308], (-0.248, 0.569]], dtype=object) 
Levels (5): Index([[-1.207, -1.0771], (-1.0771, -0.248], 
        (-0.248, 0.569], (0.569, 1.186], (1.186, 1.308]], dtype=object) 
>>> q.labels 
array([0, 1, 0, 4, 3, 2, 1, 3, 4, 2]) 

o per abbinare il tuo codice:

>>> len(q.levels) - q.labels 
array([5, 4, 5, 1, 2, 3, 4, 2, 1, 3]) 
>>> quintile(df, "A") 
>>> np.array(df["A"]) 
array([5, 4, 5, 1, 2, 3, 4, 2, 1, 3]) 
+0

grazie DSM. Non mi ero reso conto che l'output qcut() aveva etichette. Questo è proprio quello di cui avevo bisogno! – zach

+0

Grazie a @DSM, non sapevo che qcut/cut avesse un attributo labels (non viene mostrato sfortunatamente nel completamento automatico di IPython). Finora ho pensato di chiamare 'labels = False' alla funzione-call per ottenere anche le etichette. Ma è più bello come questo. – tim