Удаление строк на основе значений в других строках - PullRequest
0 голосов
/ 21 декабря 2018

Я искал способ отбросить строки из моего фрейма данных на основе условий, которые будут проверяться со значениями в другой строке.

Вот мой фрейм данных:

product product_id  account_status
prod-A  100         active
prod-A  100         cancelled
prod-A  300         active
prod-A  400         cancelled

Если строкас account_status = 'active' существует для комбинации product & и product_id, затем сохраните эту строку и удалите другие строки.

Требуемый вывод:

product product_id  account_status
prod-A  100         active
prod-A  300         active
prod-A  400         cancelled

Я видел упомянутое решение здесь , но не удалось скопировать его для строк.

Пожалуйста, предложите.

Ответы [ 2 ]

0 голосов
/ 21 декабря 2018

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

Как и другое решение, это также обобщает «приятно» для нескольких категорий и удаляет строки, соответствующие другим статусам, только в группах, где также присутствует «активный».

0 голосов
/ 21 декабря 2018

Для более общего решения можно удалить только другие значения account_status для групп, если существует хотя бы одно значение active:

print (df)
  product  product_id account_status
0  prod-A         100         active
1  prod-A         100      cancelled <- necessary remove
2  prod-A         300         active
3  prod-A         400      cancelled
4  prod-A         500         active
5  prod-A         500         active
6  prod-A         600      cancelled
7  prod-A         600      cancelled

s = df['account_status'].eq('active')
g = df.assign(A=s).groupby(['product','product_id'])['A']
mask = ~g.transform('any') | g.transform('all') | s
df = df[mask]
print (df)
  product  product_id account_status
0  prod-A         100         active
2  prod-A         300         active
3  prod-A         400      cancelled
4  prod-A         500         active
5  prod-A         500         active
6  prod-A         600      cancelled
7  prod-A         600      cancelled

Также хорошо работает с несколькими категориями:

print (df)
  product  product_id account_status
0  prod-A         100         active
1  prod-A         100      cancelled <- necessary remove
2  prod-A         100        pending <- necessary remove
3  prod-A         300         active
4  prod-A         300        pending <- necessary remove
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

s = df['account_status'].eq('active')
g = df.assign(A=s).groupby(['product','product_id'])['A']
mask = ~g.transform('any') | g.transform('all') | s
df = df[mask]
print (df)
  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
7  prod-A         500         active
8  prod-A         600        pending
9  prod-A         600      cancelled
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...