Фильтрация DataFrame по группам, где количество элементов отличается от 1

10

Я работаю с DataFrame, имеющим следующую структуру:

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

Моя цель состоит в том, чтобы просмотреть только те группы, в которых есть только один бренд X. Поскольку группа № 2 имеет два наблюдения, равных бренду X, ее следует отфильтровать из результирующего кадра данных.

Вывод должен выглядеть так:

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

Я знаю, что должен сделать groupbyстолбец для группы, а затем отфильтровать те группы, у которых число Xотличается от 1. В части фильтрации я борюсь. Любая помощь будет оценена.

glpsx
источник

Ответы:

10

Используйте series.eqдля проверки, brandравен ли X, затем групповые и transform sumи группы фильтров, в которых Xколичество равно 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
Анки
источник
8

Это должно работать также

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

Вывод

 group  brand
0   1   A
1   1   B
2   1   X
7   3   E
8   3   F
9   3   X
moys
источник
6

Сгруппируйте столбец и примените простой фильтр количества 'X'символов в группе, равной 1

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

Вывод

   group brand
0      1     A
1      1     B
2      1     X
7      3     E
8      3     F
9      3     X
Vishnudev
источник
3

Решение с 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

Мы также можем использовать DataFrame.mergeсSeries.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
источник