Réponse rapide:
Le moyen le plus simple d'obtenir le nombre de lignes par groupe est d'appeler .size()
, ce qui renvoie a Series
:
df.groupby(['col1','col2']).size()
Habituellement, vous voulez que ce résultat soit un DataFrame
(au lieu d'un Series
) afin que vous puissiez faire:
df.groupby(['col1', 'col2']).size().reset_index(name='counts')
Si vous souhaitez savoir comment calculer le nombre de lignes et d'autres statistiques pour chaque groupe, continuez à lire ci-dessous.
Exemple détaillé:
Considérez l'exemple de trame de données suivant:
In [2]: df
Out[2]:
col1 col2 col3 col4 col5 col6
0 A B 0.20 -0.61 -0.49 1.49
1 A B -1.53 -1.01 -0.39 1.82
2 A B -0.44 0.27 0.72 0.11
3 A B 0.28 -1.32 0.38 0.18
4 C D 0.12 0.59 0.81 0.66
5 C D -0.13 -1.65 -1.64 0.50
6 C D -1.42 -0.11 -0.18 -0.44
7 E F -0.00 1.42 -0.26 1.17
8 E F 0.91 -0.47 1.35 -0.34
9 G H 1.48 -0.63 -1.14 0.17
Utilisons d'abord .size()
pour obtenir le nombre de lignes:
In [3]: df.groupby(['col1', 'col2']).size()
Out[3]:
col1 col2
A B 4
C D 3
E F 2
G H 1
dtype: int64
Utilisons ensuite .size().reset_index(name='counts')
pour obtenir le nombre de lignes:
In [4]: df.groupby(['col1', 'col2']).size().reset_index(name='counts')
Out[4]:
col1 col2 counts
0 A B 4
1 C D 3
2 E F 2
3 G H 1
Inclure les résultats pour plus de statistiques
Lorsque vous souhaitez calculer des statistiques sur des données groupées, cela ressemble généralement à ceci:
In [5]: (df
...: .groupby(['col1', 'col2'])
...: .agg({
...: 'col3': ['mean', 'count'],
...: 'col4': ['median', 'min', 'count']
...: }))
Out[5]:
col4 col3
median min count mean count
col1 col2
A B -0.810 -1.32 4 -0.372500 4
C D -0.110 -1.65 3 -0.476667 3
E F 0.475 -0.47 2 0.455000 2
G H -0.630 -0.63 1 1.480000 1
Le résultat ci-dessus est un peu ennuyeux à traiter en raison des étiquettes de colonne imbriquées et également parce que le nombre de lignes est basé sur une colonne.
Pour gagner plus de contrôle sur la sortie, je divise généralement les statistiques en agrégations individuelles que je combine ensuite en utilisant join
. Cela ressemble à ceci:
In [6]: gb = df.groupby(['col1', 'col2'])
...: counts = gb.size().to_frame(name='counts')
...: (counts
...: .join(gb.agg({'col3': 'mean'}).rename(columns={'col3': 'col3_mean'}))
...: .join(gb.agg({'col4': 'median'}).rename(columns={'col4': 'col4_median'}))
...: .join(gb.agg({'col4': 'min'}).rename(columns={'col4': 'col4_min'}))
...: .reset_index()
...: )
...:
Out[6]:
col1 col2 counts col3_mean col4_median col4_min
0 A B 4 -0.372500 -0.810 -1.32
1 C D 3 -0.476667 -0.110 -1.65
2 E F 2 0.455000 0.475 -0.47
3 G H 1 1.480000 -0.630 -0.63
Notes de bas de page
Le code utilisé pour générer les données de test est indiqué ci-dessous:
In [1]: import numpy as np
...: import pandas as pd
...:
...: keys = np.array([
...: ['A', 'B'],
...: ['A', 'B'],
...: ['A', 'B'],
...: ['A', 'B'],
...: ['C', 'D'],
...: ['C', 'D'],
...: ['C', 'D'],
...: ['E', 'F'],
...: ['E', 'F'],
...: ['G', 'H']
...: ])
...:
...: df = pd.DataFrame(
...: np.hstack([keys,np.random.randn(10,4).round(2)]),
...: columns = ['col1', 'col2', 'col3', 'col4', 'col5', 'col6']
...: )
...:
...: df[['col3', 'col4', 'col5', 'col6']] = \
...: df[['col3', 'col4', 'col5', 'col6']].astype(float)
...:
Avertissement:
Si certaines des colonnes que vous agrégez ont des valeurs nulles, alors vous voulez vraiment regarder le nombre de lignes de groupe comme une agrégation indépendante pour chaque colonne. Sinon, vous pourriez être induit en erreur quant au nombre d'enregistrements réellement utilisés pour calculer des choses comme la moyenne, car les pandas supprimeront les NaN
entrées dans le calcul de la moyenne sans vous en informer.
df[['col1','col2','col3','col4']].groupby(['col1','col2']).agg(['mean', 'count'])