#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