> Modules non standards > Pandas > Calcul des agrégats sur les dataframes
Calcul des agrégats sur les dataframes
Moyenne et écart-type :
- par colonne (moyenn des valeurs de chaque ligne pour une colonne) : df.mean(axis = 0) (c'est le défaut)
- de toutes les colonnes (une valeur par ligne) : df.mean(axis = 1)
- par défaut, saute les valeurs NaN, df.mean(skipna = True) (si False, on aura NaN à chaque fois qu'il y a au moins une valeur non définie).
- on peut aussi calculer la moyenne pour une seule colonne : df['A'].mean()
- df.std() : écart-type (au sens statistique, avec n - 1). Saute les valeurs à NaN par défaut (donc renvoie NaN si seulement 0 ou 1 valeur non NaN)
Pour calculer les pourcentages d'un dataframe :
- par colonne : df / df.sum()
- par ligne : (df.T / df.T.sum()).T
Pour calculer la moyenne et l'écart-type sur plusieurs colonnes : df.agg(['mean', 'std']).T : donne une ligne par variable et 2 colonnes : mean et std.
Attention : pandas.DataFrame.std utilise ddof = 1 (donc calcule l'écart-type corrigé), tandis que numpy.std utilise ddof = 0 (donc l'écart-type non corrigé) par défaut !
Pour standardiser un dataframe :
- par colonne : (df - df.mean()) / df.std(ddof = 0)
- par ligne : (df.T - df.T.mean() / df.T.std(ddof = 0)).T
Pour avoir un dataframe avec la moyenne de chaque ligne, mais les mêmes colonnes que le dataframe de départ :
- pandas.DataFrame({x:df.mean(axis = 1) for x in df.columns}) est une solution.
- numpy.mean(df, axis = 1, keepdims = True) ne marche pas
On peut grouper un dataframe par une ou plusieurs colonne. Si
df = pandas.DataFrame({'A': ['a', 'b', 'a', 'a', 'b'], 'B': [8, 4, 5, 10, 8], 'C': ['x', 'x', 'y', 'y', 'x'], 'D': [0, 1, 2, 3, 4]}) :
- df.groupby('A') : renvoie un objet de la classe pandas.core.groupby.DataFrameGroupBy.
- df.groupby('A').sum() : groupe avec les valeurs de A et fait la somme, pour les colonnes pour lesquelles c'est possible :
B D
A
a 23 5
b 12 5
- on peut inclure plusieurs colonnes : df.groupby(['A', 'C']).sum() donne :
B D
A C
a x 8 0
y 15 5
b x 12 5
- df.groupby('A').mean() : marche même si certaines cellules sont vides.
- si on veut que les colonnes qui ont servi à faire le groupage se retrouvent comme colonnes normales (et non dans l'index) : df.groupby(['A', 'C']).sum().reset_index() donne :
A C B D
0 a x 8 0
1 a y 15 5
2 b x 12 5
- df.loc[:, ['A', 'B']].groupby('A').count() : compte le nombre de valeurs de B pour chaque groupe correspondant à une valeur de A. Attention, si B a des valeurs NaN, elles ne comptent pas !
- on peut faire simplement df.groupby('A').size() pour avoir la taille de chaque groupe.
- df.groupby('A').mean() : calcule les moyennes pour chaque valeur de A
- fonctions disponibles :
- size() : le nombre dans le groupe
- min(), max()
- mean() : moyenne.
- sum(), prod() : somme, produit
- var(), std() : variance, standard deviation (normalisés par défaut par n - 1)
- median() : médiane.
- quantile(q = 0.2) : quantile
- mad() : median absolute deviate.
- nunique() : nombre de valeurs uniques.
- rank() : rang dans le groupe.
- on peut aussi faire des groupby sur les index :
df = pandas.DataFrame({'A': [0, 1, 2], 'B': [3, 4, 5],
'C': [6, 7, 8], 'D': [9, 10, 11]})
df.columns = pandas.MultiIndex(levels = [['a', 'b'], ['A', 'B']],
labels = [[0, 0, 1, 1], [0, 1, 0, 1]])
Ca donne :
a b
A B A B
0 0 3 6 9
1 1 4 7 10
2 2 5 8 11
df.index = ['a', 'a', 'b']; df.groupby(axis = 0, level = 0).sum() donne :
A B C D
a 1 7 13 19
b 2 5 8 11
Fonction agg :
- on peut aussi faire l'aggrégation en donnant soit le le nom de la fonction, soit la fonction elle même :
- df.groupby('A').agg('min') ou df.groupby('A').agg(min)
- df.groupby('A').agg('mean') ou df.groupby('A').agg(numpy.mean)
- df.groupby('A').agg('mad') ou df.groupby('A').agg(pandas.DataFrame.mad)
- on peut faire l'aggrégation avec plusieurs stats : df.groupby('A').agg(['mad', 'mean']) : ça donne un dataframe avec un index colonne hierarchique :
B D
mad mean mad mean
A
a 1.777778 7.666667 1.111111 1.666667
b 2.000000 6.000000 1.500000 2.500000
- calcul de plusieurs stats sur plusieurs variables en même temps :
df = pandas.DataFrame({'A': ['a', 'a', 'a', 'a', 'b', 'b', 'b', 'b'],
'B': ['c', 'c', 'e', 'e', 'e', 'e', 'e', 'e'], 'X': [1, 2, 3, 4, 5, 6, 7, 8],
'Y': [10, 20, 30, 40, 50, 60, 70, 80]})
df2 = df.groupby(['A', 'B']).agg(['mean', 'std', len]).reset_index()
df2.columns = [''.join(x) for x in df2.columns.to_flat_index()]
donne :
A B Xmean Xstd Xlen Ymean Ystd Ylen
0 a c 1.5 0.707107 2 15 7.071068 2
1 a e 3.5 0.707107 2 35 7.071068 2
2 b e 6.5 1.290994 4 65 12.909944 4
- on peut aussi donner une fonction custom : df.groupby('A').agg([numpy.mean, lambda x: 100 * len(x[x > 0]) / len(x)])
- quand on a un index colonne hierarchique (multilevel ou multiindex), on peut le mettre à plat de la façon suivante : df.columns = ['_'.join(x) for x in df.columns.values]. Cela donne alors :
B_mad B_mean D_mad D_mean
A
a 1.777778 7.666667 1.111111 1.666667
b 2.000000 6.000000 1.500000 2.500000
- pour accéder aux différents niveaux du multiindex : df.columns.get_level_values(0), df.columns.get_level_values(1), ...
- si on a une colonne sur laquelle on calcule des statistiques, on peut aussi faire : df.groupby('A')['B'].agg({'MAD': 'mad', 'AVG': 'mean'}) :
AVG MAD
A
a 7.666667 1.777778
b 6.000000 2.000000
- S'il n'y a qu'une seule colonne numérique et que les autres servent à l'aggrégation, c'est beaucoup plus simple : df2 = df.loc[:, ['A', 'B', 'C']].groupby(['A', 'C']).agg(['mean', 'std', len]).reset_index(); df2.columns = [x[0] if x[1] == '' else x[1] for x in df2.columns.tolist()]; df2 donne :
A C mean std len
0 a x 8.0 NaN 1
1 a y 7.5 3.535534 2
2 b x 6.0 2.828427 2
apply : applique une fonction sur chaque groupe. La fonction recoit en argument un dataframe par groupe :
Copyright python-simple.com
programmer en python, tutoriel python, graphes en python, Aymeric Duclert