Создать двоичный столбец в кадре данных Pandas на основе приоритета - PullRequest
3 голосов
/ 15 апреля 2019

У меня есть pandas dataframe, который выглядит примерно так:

Item    Status
123     B
123     BW
123     W 
123     NF
456     W
456     BW
789     W
789     NF
000     NF

И мне нужно создать новый столбец Value, который будет либо 1, либо 0 в зависимости от значений в Itemи Status столбцы.Присвоение значения 1 имеет приоритет в следующем порядке: B, BW, W, NF.Таким образом, с использованием приведенного выше примера данных, результат должен быть:

Item    Status    Value
123     B         1
123     BW        0
123     W         0
123     NF        0
456     W         0
456     BW        1
789     W         1
789     NF        0
000     NF        1

Использование Python 3.7.

Ответы [ 3 ]

2 голосов
/ 15 апреля 2019

Принимая ваш оригинальный фрейм данных в качестве входных данных df фрейм данных, следующий код даст желаемый результат:

#dictionary assigning order of priority to status values
priority_map = {'B':1,'BW':2,'W':3,'NF':4}

#new temporary column that converts Status values to order of priority values
df['rank'] = df['Status'].map(priority_map)

#create dictionary with Item as key and lowest rank value per Item as value
lowest_val_dict = df.groupby('Item')['rank'].min().to_dict()

#new column that assigns the same Value to all rows per Item
df['Value'] = df['Item'].map(lowest_val_dict)

#replace Values where rank is different with 0's
df['Value'] = np.where(df['Value'] == df['rank'],1,0)

#delete rank column
del df['rank']
1 голос
/ 20 апреля 2019

Я бы предпочел подход, при котором статус является упорядоченным pd.Categorical, потому что а) это то, что есть, и б) это гораздо более читабельно: если у вас это есть, вы просто сравните, если значениеравен max его группы:

df['Status'] = pd.Categorical(df['Status'], categories=['NF', 'W', 'BW', 'B'],
                              ordered=True)
df['Value'] = df.groupby('Item')['Status'].apply(lambda x: (x == x.max()).astype(int))

#   Item Status  Value
#0   123      B      1
#1   123     BW      0
#2   123      W      0
#3   123     NF      0
#4   456      W      0
#5   456     BW      1
#6   789      W      1
#7   789     NF      0
#8     0     NF      1
0 голосов
/ 15 апреля 2019

Я мог бы помочь вам концептуально, объяснив некоторые шаги, которые я бы сделал:

  1. Создайте новый столбец Значение и заполните его нулями np.zeros() или pd.fillna()
  2. Сгруппируйте фрейм данных по Элементу с помощью groupby = pd.groupby('Item')
  3. Итерируйте по всем найденным группам for name, group in groupby:
  4. Используя простую функцию с if, пользовательскую очередь приоритетов,Пользовательские критерии сортировки или любой другой предпочтительный метод определяют, какая запись имеет более высокий приоритет" на это значение 1 имеет приоритет в следующем порядке: B, BW, W, NF " и присвоить значение 1 столбцу Значение group.loc[entry]['Value'] == 0

    Допустим, мы смотрим на группу '123':

     Item    Status    Value
     -------------------------
     123     B         0 (before 0, after 1)
     123     BW        0
     123     W         0
     123     NF        0
    

    Поскольку строка [123, 'B', 0] имелаНаивысший приоритет, основанный на ваших критериях, вы изменяете на [123, 'B', 1]

  5. Когда закончите, создайте кадр данных обратно из объекта groupby, и все готово.У вас есть много возможностей для этого, можете проверить здесь: Преобразование объекта Pandas GroupBy в DataFrame

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...