Pandas Groupby с лямбда и в списке - PullRequest
       9

Pandas Groupby с лямбда и в списке

0 голосов
/ 11 сентября 2018

У меня есть следующий фрейм данных

df = pd.DataFrame({'ItemType': ['Red', 'White', 'Red', 'Blue', 'White', 'White', 'White', 'Green'], 
               'ItemPrice': [10, 11, 12, 13, 14, 15, 16, 17], 
               'ItemID': ['A', 'A', 'B', 'B', 'C', 'C', 'D', 'D']})

Я хотел бы получить записи (строки) с ItemID, которые содержат только «белый» ItemType в виде DataFrame

Я попытался следующее решение:

types = ['Red','Blue','Green']

~df.groupby('ItemID')['ItemType'].any().apply(lambda u: u in(types))

Но это дает мне неверный результат (D должен быть False) и в форме серии.

A False
B False
C True
D True

Спасибо!

Ответы [ 2 ]

0 голосов
/ 11 сентября 2018

Альтернативным методом является вычисление массива небелых ItemID значений.Затем отфильтруйте ваш фрейм данных:

non_whites = df.loc[df['ItemType'].ne('White'), 'ItemID'].unique()

res = df[~df['ItemID'].isin(non_whites)]

print(res)

  ItemType  ItemPrice ItemID
4    White         14      C
5    White         15      C

Вы также можете использовать GroupBy, но это не является абсолютно необходимым.

0 голосов
/ 11 сентября 2018

Вам следует избегать использования apply здесь, так как это обычно довольно медленно. Вместо этого присвойте столбец flag перед groupby, а затем используйте all, чтобы подтвердить, что ни одно из значений групп не содержится в types:

df.assign(flag=~df.ItemType.isin(types)).groupby('ItemID').flag.all()

ItemID
A    False
B    False
C     True
D    False
Name: flag, dtype: bool

Однако, чтобы продемонстрировать логику операции и показать, что было неверно в вашем подходе, вот рабочая версия, использующая apply:

~df.groupby('ItemID').ItemType.apply(lambda x: any(i in types for i in x))

Вам нужно использовать any внутри лямбды, в отличие от серии, прежде чем использовать apply.


Для доступа к строкам, где выполняется это условие, вы можете использовать transform:

df[df.assign(flag=~df.ItemType.isin(types)).groupby('ItemID').flag.transform('all')]

  ItemType  ItemPrice ItemID
4    White         14      C
5    White         15      C
...