IMO, groupby
не требуется (я говорю это, потому что вы пометили свой вопрос соответственно), вы можете использовать sort_values
и drop_duplicates
, используя тот факт, что "активный" <"отменен", лексикографически: </p>
(df.sort_values(['account_status'])
.drop_duplicates(['product', 'product_id'])
.sort_index())
product product_id account_status
0 prod-A 100 active
2 prod-A 300 active
3 prod-A 400 cancelled
В духе согласованности других ответов вы можете взглянуть на groupby
решение, включающее duplicated
и маскировку.
df
product product_id account_status
0 prod-A 100 active
1 prod-A 100 cancelled
2 prod-A 100 pending
3 prod-A 300 active
4 prod-A 300 pending
5 prod-A 400 cancelled
6 prod-A 500 active
7 prod-A 500 active
8 prod-A 600 pending
9 prod-A 600 cancelled
m1 = (df.assign(m=df.account_status.eq('active'))
.groupby(['product', 'product_id'])['m']
.transform('any'))
m2 = df.duplicated(['product', 'product_id'])
df[~(m1 & m2)]
product product_id account_status
0 prod-A 100 active
3 prod-A 300 active
5 prod-A 400 cancelled
6 prod-A 500 active
8 prod-A 600 pending
9 prod-A 600 cancelled
Как и другое решение, это также обобщает «приятно» для нескольких категорий и удаляет строки, соответствующие другим статусам, только в группах, где также присутствует «активный».