web-dev-qa-db-fra.com

Échantillonnez chaque groupe après pandas groupby

Je sais que cela a dû être répondu quelque part, mais je ne pouvais tout simplement pas le trouver.

Problème: échantillonnez chaque groupe après une opération groupby.

import pandas as pd

df = pd.DataFrame({'a': [1,2,3,4,5,6,7],
                   'b': [1,1,1,0,0,0,0]})

grouped = df.groupby('b')

# now sample from each group, e.g., I want 30% of each group
23
gongzhitaao

Appliquez un lambda et appelez sample avec param frac:

In [2]:
df = pd.DataFrame({'a': [1,2,3,4,5,6,7],
                   'b': [1,1,1,0,0,0,0]})
​
grouped = df.groupby('b')
grouped.apply(lambda x: x.sample(frac=0.3))

Out[2]:
     a  b
b        
0 6  7  0
1 2  3  1
43
EdChum

Échantillonnez une fraction de chaque groupe

Vous pouvez utiliser GroupBy.apply avec sample . Vous n'avez pas besoin d'utiliser un lambda; apply accepte les arguments de mots clés:

frac = .3
df.groupby('b').apply(pd.DataFrame.sample, frac=.3)
     a  b
b        
0 6  7  0
1 0  1  1

Si le MultiIndex n'est pas requis, vous pouvez spécifier group_keys=False À groupby:

df.groupby('b', group_keys=False).apply(pd.DataFrame.sample, frac=.3)

   a  b
6  7  0
2  3  1

Exemples de lignes N de chaque groupe

apply est lent. Si votre cas d'utilisation consiste à échantillonner un nombre fixe de lignes, vous pouvez mélanger le DataFrame au préalable, puis utiliser GroupBy.head .

df.sample(frac=1).groupby('b').head(2)

   a  b
2  3  1
5  6  0
1  2  1
4  5  0

C'est la même chose que df.groupby('b', group_keys=False).apply(pd.DataFrame.sample, n=N), mais plus rapide :

%%timeit df.groupby('b', group_keys=False).apply(pd.DataFrame.sample, n=2)  
                                                 # 3.19 ms ± 90.5 µs
%timeit df.sample(frac=1).groupby('b').head(2)   # 1.56 ms ± 103 µs
5
cs95