Filtrage de DataFrame sur des groupes où le nombre d'éléments est différent de 1

10

Je travaille avec un DataFrame ayant la structure suivante:

import pandas as pd

df = pd.DataFrame({'group':[1,1,1,2,2,2,2,3,3,3],
                   'brand':['A','B','X','C','D','X','X','E','F','X']})

print(df)

   group brand
0      1     A
1      1     B
2      1     X
3      2     C
4      2     D
5      2     X
6      2     X
7      3     E
8      3     F
9      3     X

Mon objectif est de ne voir que les groupes ayant exactement une marqueX qui leur est associée. Étant donné que le groupe numéro 2 a deux observations égales à la marque X, il doit être filtré du DataFrame résultant.

La sortie devrait ressembler à ceci:

   group brand
0      1     A
1      1     B
2      1     X
3      3     E
4      3     F
5      3     X

Je sais que je devrais faire un groupbysur la colonne de groupe, puis filtrer les groupes ayant un nombre Xdifférent de 1. La partie filtrage est l'endroit où je lutte. Toute aide serait appréciée.

glpsx
la source

Réponses:

10

Utilisez series.eqpour vérifier si brandest égal à X, puis groupez et transform sumet filtrez les groupes dont le Xnombre est égal à 1:

df[df['brand'].eq('X').groupby(df['group']).transform('sum').eq(1)]

   group brand
0      1     A
1      1     B
2      1     X
7      3     E
8      3     F
9      3     X
anky
la source
8

Cela devrait aussi fonctionner

df[df.groupby(['group'])['brand'].transform('sum').str.count('X').eq(1)]

Production

 group  brand
0   1   A
1   1   B
2   1   X
7   3   E
8   3   F
9   3   X
moys
la source
6

Colonne Groupby et appliquez un simple filtre de nombre de 'X'caractères dans le groupe égal à 1

df.groupby('group').filter(lambda x: x['brand'].str.count('X').sum() == 1)

Production

   group brand
0      1     A
1      1     B
2      1     X
7      3     E
8      3     F
9      3     X
Vishnudev
la source
3

Solution avec pd.crosstab

df[df['group'].map(pd.crosstab(df['group'],df['brand'])['X'].eq(1))]

#   group brand
#0      1     A
#1      1     B
#2      1     X
#7      3     E
#8      3     F
#9      3     X

Nous pouvons également utiliser DataFrame.mergeavecSeries.drop_duplicates

df.merge(df.loc[df.brand.eq('X'),'group'].drop_duplicates(keep = False),on='group')
#   group brand
#0      1     A
#1      1     B
#2      1     X
#3      3     E
#4      3     F
#5      3     X
ansev
la source