Ok, voici donc ce que j'essaie de faire:

J'ai un DataFrame comme celui-ci:

data = pd.DataFrame(
{'a' : [1,1,1,2,2,3,3,3],
 'b' : [23,45,62,24,45,34,25,62],
 })

J'ai réussi à calculer la moyenne de la colonne 'a' groupée par la colonne 'b' en utilisant le code suivant:

data.groupby('b', as_index=False)['a'].mean()

Qui a abouti à un DataFrame comme celui-ci:

current DataFrame

Cependant, je voudrais seulement calculer la moyenne des valeurs de 'b' qui se produisent plus d'une fois dans le DataFrame, résultant en un Dataframe comme ceci:

Desired DataFrame

J'ai essayé de le faire en utilisant la ligne suivante:

data.groupby('b', as_index=False).filter(lambda group: len(group)>1)['a'].mean()

Mais il en résulte la moyenne des lignes 1, 2, 4 et 7, ce qui n'est évidemment pas ce que je veux. Quelqu'un peut-il m'aider à obtenir le DataFrame souhaité et me dire ce que je me trompe sur l'utilisation de la fonction de filtrage?

Je vous remercie!

3
Vinícius Silva 20 nov. 2018 à 20:56

3 réponses

Meilleure réponse

Regroupement sur doublons

Vous pouvez le faire avec data['b'].duplicated(keep=False) pour créer d'abord un masque booléen:

>>> data[data['b'].duplicated(keep=False)].groupby('b', as_index=False)['a'].mean()                                                                         
    b    a
0  45  1.5
1  62  2.0

data.b.duplicated(keep=False) marque toutes les occurrences dupliquées comme True et vous permet de restreindre la sortie à ces lignes:

>>> data.b.duplicated(keep=False)                                                                                                                        
0    False
1     True
2     True
3    False
4     True
5    False
6    False
7     True
Name: b, dtype: bool

>>> data[data.b.duplicated(keep=False)]                                                                                                                  
   a   b
1  1  45
2  1  62
4  2  45
7  3  62

Mise à jour: regroupement par nombre arbitraire d'occurrences

Cette solution peut-elle être généralisée pour rechercher un nombre arbitraire d'occurrences? Disons que je voulais calculer la moyenne uniquement pour les valeurs survenues plus de 5 fois sur le DataFrame.

Dans ce scénario, vous devez générer un masque booléen de la même forme que dans l'exemple ci-dessus, mais en utilisant une approche légèrement différente.

Voici une façon:

>>> vc = data['b'].map(data['b'].value_counts(sort=False))
>>> vc                                                                                                                                                   

0    1
1    2
2    2
3    1
4    2
5    1
6    1
7    2
Name: b, dtype: int64

Ce sont les comptes élément par élément pour chaque élément de b. Pour obtenir ceci à un masque (disons que vous voulez des moyens pour seulement count == 2, ce qui est le même que ci-dessus dans cet exemple, mais pourrait être étendu pour tout int):

mask = vc == 2  # or > 5, in your case
data[mask].groupby('b', as_index=False)['a'].mean()
3
Brad Solomon 20 nov. 2018 à 18:20

Vous pouvez filtrer avant votre trame de données via loc avant groupby:

df = pd.DataFrame({'a' : [1,1,1,2,2,3,3,3],
                   'b' : [23,45,62,24,45,34,25,62]})

counts = df['b'].value_counts()

res = df.loc[df['b'].isin(counts[counts > 1].index)]\
        .groupby('b', as_index=False)['a'].mean()

print(res)

    b    a
0  45  1.5
1  62  2.0
1
jpp 20 nov. 2018 à 18:01

Tu étais assez proche:

data.groupby('b').filter(lambda g:len(g)>1).groupby('b',as_index=False).mean()

Donne la réponse que vous cherchiez:

    b    a
0  45  1.5
1  62  2.0
1
Brad Solomon 20 nov. 2018 à 18:08