Python: sélection aléatoire par groupe

Dire que j'ai un dataframe qui ressemble à:

Name Group_Id
AAA  1
ABC  1
CCC  2
XYZ  2
DEF  3 
YYH  3

Comment puis-je choisir au hasard une (ou plusieurs) rangée pour chaque Group_Id? Dites que je veux un tirage au sort par Group_Id, j'obtiens:

Name Group_Id
AAA  1
XYZ  2
DEF  3
21
demandé sur Plug4 2014-03-18 10:50:40

7 réponses

size = 2        # sample size
replace = True  # with replacement
fn = lambda obj: obj.loc[np.random.choice(obj.index, size, replace),:]
df.groupby('Group_Id', as_index=False).apply(fn)
16
répondu behzad.nouri 2014-03-18 11:07:32

0.16.x à partir de pd.DataFrame.sample fournit un moyen de retourner un échantillon aléatoire d'articles à partir d'un axe d'objet.

In [664]: df.groupby('Group_Id').apply(lambda x: x.sample(1)).reset_index(drop=True)
Out[664]:
  Name  Group_Id
0  ABC         1
1  XYZ         2
2  DEF         3
10
répondu Zero 2017-09-09 07:32:17

utilisant groupby et random.choix dans un élégant une ligne:

df.groupby('Group_Id').apply(lambda x :x.iloc[random.choice(range(0,len(x)))])
9
répondu grasshopper 2014-03-18 11:30:43

il y a deux façons de faire cela très simplement, une sans utiliser quoi que ce soit sauf la syntaxe de base des pandas:

df[['x','y']].groupby('x').agg(pd.DataFrame.sample)

cela prend 14.4 ms avec un ensemble de données de 50k rangées.

l'autre méthode, légèrement plus rapide, implique num PY.

df[['x','y']].groupby('x').agg(np.random.choice)

cela prend 10.9 ms avec (le même) ensemble de données de ligne de 50k.

en général, lorsqu'on utilise pandas, il est préférable de s'en tenir à sa syntaxe native. Surtout pour les débutants.

2
répondu mikkokotila 2018-04-05 14:14:54

pour sélectionner au hasard juste une ligne par groupe essayer df.sample(frac = 1.0).groupby('Group_Id').head(1)

2
répondu ihadanny 2018-08-18 09:47:15

en utilisant random.choice, vous pouvez faire quelque chose comme ceci:

import random
name_group = {'AAA': 1, 'ABC':1, 'CCC':2, 'XYZ':2, 'DEF':3, 'YYH':3}

names = [name for name in name_group.iterkeys()] #create a list out of the keys in the name_group dict

first_name = random.choice(names)
first_group = name_group[first_name]
print first_name, first_group

random.choice(seq)

Return a random element from the non-empty sequence seq. If seq is empty, raises IndexError.
1
répondu gravetii 2014-03-18 07:10:23

Vous pouvez utiliser une combinaison de pandas.groupby,pandas.concat et random.sample:

import pandas as pd
import random

df = pd.DataFrame({
        'Name': ['AAA', 'ABC', 'CCC', 'XYZ', 'DEF', 'YYH'],
        'Group_ID': [1,1,2,2,3,3]
     })

grouped = df.groupby('Group_ID')
df_sampled = pd.concat([d.ix[random.sample(d.index, 1)] for _, d in grouped]).reset_index(drop=True)
print df_sampled

Sortie:

   Group_ID Name
0         1  AAA
1         2  XYZ
2         3  DEF
1
répondu YS-L 2014-03-18 07:43:39