web-dev-qa-db-fra.com

Passer les percentiles à la fonction d'agrégation des pandas

Je souhaite passer la fonction numpy percentile () à la fonction agg () de pandas comme je le fais ci-dessous avec diverses autres fonctions de statistiques numpy.

À l'heure actuelle, j'ai un cadre de données qui ressemble à ceci:

AGGREGATE   MY_COLUMN
A           10
A           12
B           5
B           9
A           84
B           22

Et mon code ressemble à ceci:

grouped = dataframe.groupby('AGGREGATE')
column = grouped['MY_COLUMN']
column.agg([np.sum, np.mean, np.std, np.median, np.var, np.min, np.max])

Le code ci-dessus fonctionne, mais je veux faire quelque chose comme 

column.agg([np.sum, np.mean, np.percentile(50), np.percentile(95)])

c'est-à-dire spécifier différents centiles pour revenir de agg ()

Comment cela devrait-il être fait?

24
slizb

Peut-être pas très efficace, mais une solution serait de créer une fonction vous-même:

def percentile(n):
    def percentile_(x):
        return np.percentile(x, n)
    percentile_.__= 'percentile_%s' % n
    return percentile_

Ensuite, incluez ceci dans votre agg:

In [11]: column.agg([np.sum, np.mean, np.std, np.median,
                     np.var, np.min, np.max, percentile(50), percentile(95)])
Out[11]:
           sum       mean        std  median          var  amin  amax  percentile_50  percentile_95
AGGREGATE
A          106  35.333333  42.158431      12  1777.333333    10    84             12           76.8
B           36  12.000000   8.888194       9    79.000000     5    22             12           76.8

Notez bien que c’est ainsi que cela se passe devrait.

56
Andy Hayden

Pour être plus précis, si vous souhaitez simplement agréger vos résultats de groupe de pandas à l’aide de la fonction de centile, la fonction python lambda constitue une solution très soignée. Utiliser la notation de la question, agrégée par le centile 95, devrait être:

dataframe.groupby('AGGREGATE').agg(lambda x: np.percentile(x['COL'], q = 95))

Vous pouvez également affecter cette fonction à une variable et l'utiliser conjointement avec d'autres fonctions d'agrégation.

9
MonkeyButter

Essayez ceci pour les centiles 50% et 95%:

column.describe( percentiles = [ 0.5, 0.95 ] )
7
scottlittle

Plusieurs fonctions peuvent être appelées comme ci-dessous:

import pandas as pd

import numpy as np

import random

C = ['Ram', 'Ram', 'Shyam', 'Shyam', 'Mahima', 'Ram', 'Ram', 'Shyam', 'Shyam', 'Mahima']

A = [ random.randint(0,100) for i in range(10) ]

B = [ random.randint(0,100) for i in range(10) ]

df = pd.DataFrame({ 'field_A': A, 'field_B': B, 'field_C': C })

print(df)

d = df.groupby('field_C')['field_A'].describe()[['mean', 'count', '25%', '50%', '75%']]
print(d)

J'étais incapable d'appeler la médiane à cet égard, mais je pouvais utiliser d'autres fonctions.

1
Fakira

J'aime beaucoup la solution donnée par Andy Hayden , cependant, cela posait de nombreux problèmes:

  • Si le cadre de données comporte plusieurs colonnes, il s’est agrégé sur les colonnes plutôt que sur les lignes?
  • Pour moi, les noms de ligne étaient percentile_0.5 (point au lieu de trait de soulignement). Pas sûr de ce qui a causé cela, probablement que j'utilise Python 3.
  • Besoin d'importer numpy également au lieu de rester dans des pandas (je sais que numpy est importé implicitement dans des pandas ...)

Voici une version mise à jour qui résout ces problèmes:

def percentile(n):
    def percentile_(x):
        return x.quantile(0.5)
    percentile_.__= 'percentile_{:2.0f}'.format(n*100)
    return percentile_
0
Thomas