создайте новый столбец на основе нескольких условий и нескольких панд столбцов

#python #pandas

Вопрос:

Учитывая, что у меня также есть другие столбцы рядом с этими столбцами ниже, я хочу создать новый столбец из этих 3 столбцов, которые определяют окончательный статус каждой строки.

 status_1                        status_2       status_3
a_accepted_with_comment         a_revised     c_approved
a_accepted_with_comment         c_rejected       nan
a_rejected                      a_approved       nan
a_rejected                         nan           nan
 

Из столбца 3, если в последнем столбце, имеющем значение, указано c_approved, то в новом столбце будет указано утверждено

Из столбца 3, если последний столбец со значением показывает c_rejected, то новый столбец даст отклоненный

Из столбца 3, если в последнем столбце, имеющем значение, указано значение a_approved, то в новом столбце будет указано пересмотренное значение

Из столбца 3, если последний столбец со значением показывает a_rejected, то новый столбец выдаст отклоненный

Итоговый стол будет выглядеть так:

 status_1                        status_2       status_3       final_status
a_accepted_with _comment         a_revised     c_approved       approved
a_accepted_with_comment         c_rejected       nan           rejected
b_rejected                      a_approved       nan           revised
a_rejected                       nan             nan           rejected                            
 

Как я могу создать этот новый столбец с таким множественным условием в python?

Заранее спасибо.

Ответ №1:

Вы можете использовать ffill и map отслеживать каждый из ваших критериев и то, к чему они приводят.

 response_rules = {
    "c_approved": "approved",
    "c_rejected": "rejected",
    "a_approved": "revised",
    "a_rejected": "rejected"
}

df["final_status"] = df.ffill(axis=1)["status_3"].map(response_rules)
print(df)
                  status_1    status_2    status_3 final_status
0  a_accepted_with_comment   a_revised  c_approved     approved
1  a_accepted_with_comment  c_rejected         NaN     rejected
2               a_rejected  a_approved         NaN      revised
3               a_rejected         NaN         NaN     rejected

 

Если у вас много правил, лучшим шаблоном проектирования может быть сохранение легко читаемого/редактируемого словаря, который сопоставляет результат с каждым критерием, а затем инвертирует его перед вызовом .map

 response_rules = {
    "approved": ["c_approved"],
    "rejected": ["c_rejected", "a_rejected"],
    "revised": ["a_approved"]
}
# invert dictionary
inverted_rules = {vv: k for k, v in response_rules.items() for vv in v}

# same as before
df["final_status"] = df.ffill(axis=1)["status_3"].map(inverted_rules)

print(df)
                  status_1    status_2    status_3 final_status
0  a_accepted_with_comment   a_revised  c_approved     approved
1  a_accepted_with_comment  c_rejected         NaN     rejected
2               a_rejected  a_approved         NaN      revised
3               a_rejected         NaN         NaN     rejected



# Just so you can see:
print(inverted_rules) 
{'a_approved': 'revised',
 'a_rejected': 'rejected',
 'c_approved': 'approved',
 'c_rejected': 'rejected'}
 

Комментарии:

1. спасибо за ответ! В моем случае столбец status_3 не всегда является столбцами для чтения, чтобы дать final_status. Это может быть из status_2 или status_1. Как я могу это сделать?

2. IIUC, призыв .ffill(axis=1) позаботиться об этом. По сути, мы распространяем последний допустимый non-NAN ответ слева направо до тех пор, пока столбец «status_3» полностью не заполнится последней допустимой записью. Итак, результат df.ffill(axis=1)["status_3"] выходных данных: ["c_approved", "c_rejected", "a_approved", "a_rejected"] это то, над чем мы работаем, когда связываем вызов с .map(...)

Ответ №2:

Давайте попробуем ffill с np.select

 s = df.ffill(1).iloc[:,-1]
c1 = s=='c_approved'
c2 = s.isin(['c_rejected','a_rejected'])
c3 = s=='a_approved'
df['new'] = np.select([c1,c2,c3],['approve','rejected','revised'])
df
Out[210]: 
                  status_1    status_2    status_3       new
0  a_accepted_with_comment   a_revised  c_approved   approve
1  a_accepted_with_comment  c_rejected         NaN  rejected
2               a_rejected  a_approved         NaN   revised
3               a_rejected         NaN         NaN  rejected