Comment accéder aux pandas groupby dataframe par clé

154

Comment accéder au dataframe groupby correspondant dans un objet groupby par la clé?

Avec le groupby suivant:

rand = np.random.RandomState(1)
df = pd.DataFrame({'A': ['foo', 'bar'] * 3,
                   'B': rand.randn(6),
                   'C': rand.randint(0, 20, 6)})
gb = df.groupby(['A'])

Je peux le parcourir pour obtenir les clés et les groupes:

In [11]: for k, gp in gb:
             print 'key=' + str(k)
             print gp
key=bar
     A         B   C
1  bar -0.611756  18
3  bar -1.072969  10
5  bar -2.301539  18
key=foo
     A         B   C
0  foo  1.624345   5
2  foo -0.528172  11
4  foo  0.865408  14

Je souhaite pouvoir accéder à un groupe par sa clé:

In [12]: gb['foo']
Out[12]:  
     A         B   C
0  foo  1.624345   5
2  foo -0.528172  11
4  foo  0.865408  14

Mais quand j'essaye de faire ça avec, gb[('foo',)]j'obtiens ce pandas.core.groupby.DataFrameGroupBytruc d'objet bizarre qui ne semble pas avoir de méthodes qui correspondent au DataFrame que je veux.

Le mieux que je puisse penser est:

In [13]: def gb_df_key(gb, key, orig_df):
             ix = gb.indices[key]
             return orig_df.ix[ix]

         gb_df_key(gb, 'foo', df)
Out[13]:
     A         B   C
0  foo  1.624345   5
2  foo -0.528172  11
4  foo  0.865408  14  

mais c'est un peu méchant, compte tenu de la gentillesse des pandas dans ces domaines.
Quelle est la manière intégrée de faire cela?

barbe
la source

Réponses:

192

Vous pouvez utiliser la get_groupméthode:

In [21]: gb.get_group('foo')
Out[21]: 
     A         B   C
0  foo  1.624345   5
2  foo -0.528172  11
4  foo  0.865408  14

Remarque: Cela ne nécessite pas la création d'un dictionnaire / copie intermédiaire de chaque sous-trame de données pour chaque groupe, ce sera donc beaucoup plus efficace en mémoire que la création du dictionnaire naïf avec dict(iter(gb)). En effet, il utilise des structures de données déjà disponibles dans l'objet groupby.


Vous pouvez sélectionner différentes colonnes à l'aide du découpage groupby:

In [22]: gb[["A", "B"]].get_group("foo")
Out[22]:
     A         B
0  foo  1.624345
2  foo -0.528172
4  foo  0.865408

In [23]: gb["C"].get_group("foo")
Out[23]:
0     5
2    11
4    14
Name: C, dtype: int64
Andy Hayden
la source
72

Wes McKinney (auteur de pandas) en Python pour l'analyse de données fournit la recette suivante:

groups = dict(list(gb))

qui renvoie un dictionnaire dont les clés sont vos étiquettes de groupe et dont les valeurs sont des DataFrames, ie

groups['foo']

vous donnera ce que vous recherchez:

     A         B   C
0  foo  1.624345   5
2  foo -0.528172  11
4  foo  0.865408  14
JD Margulici
la source
1
Merci, c'est très utile. Comment puis-je modifier le code pour groups = dict(list(gb))ne faire que stocker la colonne C? Disons que je ne suis pas intéressé par les autres colonnes et que je ne souhaite donc pas les stocker.
Zhubarb
5
Réponse:dict(list( df.groupby(['A'])['C'] ))
Zhubarb
4
Remarque: c'est plus efficace (mais équivalent) à utiliser dict(iter(g)). (bien que ce get_groupsoit le meilleur moyen / car cela n'implique pas de créer un dictionnaire / vous garde dans les pandas!: D)
Andy Hayden
Je n'ai pas pu utiliser les groupes (dict (list (gb)) mais vous pouvez créer un dictionnaire de la manière suivante: gb_dict = {str(indx): str(val) for indx in gb.indx for val in gb.some_key}puis récupérer la valeur viagb_dict[some_key]
user2476665
Il suffit de l'utiliser get_group(), cette recette n'est plus nécessaire depuis des années.
smci
20

Plutôt que

gb.get_group('foo')

Je préfère utiliser gb.groups

df.loc[gb.groups['foo']]

Parce que de cette façon, vous pouvez également choisir plusieurs colonnes. par exemple:

df.loc[gb.groups['foo'],('A','B')]
LegitMe
la source
4
Remarque: vous pouvez sélectionner différentes colonnes à l'aide de gb[["A", "B"]].get_group("foo").
Andy Hayden le
6
gb = df.groupby(['A'])

gb_groups = grouped_df.groups

Si vous recherchez des objets groupby sélectifs, faites: gb_groups.keys (), et saisissez la clé souhaitée dans la liste de clés suivante.

gb_groups.keys()

key_list = [key1, key2, key3 and so on...]

for key, values in gb_groups.iteritems():
    if key in key_list:
        print df.ix[values], "\n"
Surya
la source
1

Je cherchais un moyen d'échantillonner quelques membres de l'objet GroupBy - je devais répondre à la question posée pour y parvenir.

créer un objet groupby

grouped = df.groupby('some_key')

choisissez N dataframes et saisissez leurs indices

sampled_df_i  = random.sample(grouped.indicies, N)

attrapez les groupes

df_list  = map(lambda df_i: grouped.get_group(df_i), sampled_df_i)

facultativement - transformer tout cela en un seul objet dataframe

sampled_df = pd.concat(df_list, axis=0, join='outer')
meyerson
la source
1
Cela ne fonctionne pas:sampled_df_i = random.sample(grouped.indicies, N)
irene
@irene - pouvez-vous fournir un lien vers un exemple plus long / plus de contexte?
meyerson
J'obtiens l'erreur suivante:AttributeError: 'DataFrameGroupBy' object has no attribute 'indicies'
irene