Условный флаг на основе Groupby Python - PullRequest
0 голосов
/ 17 февраля 2020

Я хочу использовать условные операторы для создания флага на основе идентификатора и порядка приоритета -

Кадр данных -

    df=pd.DataFrame({'id':[1,1,1,1,2,3,3,3],
     'var':['Apple','Banana','Orange','Mango', 'Mango', 'Banana','Orange','Mango'],
      'flag':[1,1,1,1,1,1,1,1]})

Порядок приоритета - Apple> Banana> Orange

Условия -

1 - если в идентификаторе присутствуют Apple, Banana & Man go, тогда флаг Banana & Ornage становится равным 0, для Man go никакого влияния не будет, будет 1.

2 - Если присутствуют банан и апельсин, тогда флаг для оранжевого станет 0

Вывод -

     df=pd.DataFrame({'id':[1,1,1,1,2,3,3,3],
     'var':['Apple','Banana','Orange','Mango', 'Mango', 'Banana','Orange','Mango'],
      'flag':[1,0,0,1,1,1,0,1]})

Метод -

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

Я считаю, что усложнил это и поступил неправильно. Пожалуйста, руководство.

group_test = df.groupby(['id'],as_index=False).var.agg(lambda x: x.unique().tolist())
list_1 = ['Apple','Banana','Orange']
list_2 = ['Banana', 'Orange']

Ответы [ 2 ]

1 голос
/ 17 февраля 2020

Мы можем l oop пройти через каждый кусок объекта GroupBy и установить для столбца flag значение, требуемое для строк, удовлетворяющих определенному условию, используя loc.

Сначала давайте установим все наших условий раньше времени.

match1 = {'Apple', 'Banana', 'Mango'}
match2 = {'Banana', 'Orange'}
p_cond = (df['var'].str.contains('Banana|Orange', regex=True))
s_cond = (df['var'] == 'Orange')

Затем мы можем l oop поверх нашего сгруппированного объекта, установив столбец flag, если он соответствует нашим критериям .

for k, v in df.groupby('id')['var']:
    vals = set(v)
    id_cond = (df['id'] == k)

    if vals.issuperset(match1):
        df.loc[id_cond & p_cond, 'flag'] = 0
    elif vals.issuperset(match2):
        df.loc[id_cond & s_cond, 'flag'] = 0
    else:
        continue

Это дает нам следующие результаты.

   flag  id     var
0     1   1   Apple
1     0   1  Banana
2     0   1  Orange
3     1   1   Mango
4     1   2   Mango
5     1   3  Banana
6     0   3  Orange
7     1   3   Mango
0 голосов
/ 17 февраля 2020

Это решение, которое работает с данными данными. Я не думаю, что это сработало бы, если бы у вас были заказы на (n-2) категорий, где n = количество категорий.

Это более общий ответ, если вы хотите определить Высшую категорию для каждого id

Редактировать: Если у вас есть небольшой набор категорий, которые определяют при заказе просто объедините их в категорию other, которой можно назначить последний заказ. Этого должно быть достаточно

import pandas as pd
df=pd.DataFrame({'id':[1,1,1,1,2,3,3,3],
     'var':['Apple','Banana','Orange','Mango', 'Mango', 'Banana','Orange','Mango'],
      'flag':[1,1,1,1,1,1,1,1]})

# create a categorical array with the orders set this way.
# this keeps the ordering Apple > Banana > Orange > Mango
df['category'] = pd.Categorical(df['var'], ordered=True, categories=reversed(['Apple', 'Banana', 'Orange', 'Mango']))

# group by id and just get a boolean of whether var = max category
# for each id subset, compare each var to the maximum category in that subset
df['highest_level'] = df.groupby('id').apply(lambda df_: 1 * (df_['var'] == df_['category'].max())).reset_index(drop=True)

# put mango back to 1 - since Mango was the lowest in the order
# the only times Mango would have a highest_level = 1 would be
# when the entire subset only has Mango var
df.loc[df['var'] == 'Mango', 'highest_level'] = 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...