Обновление значения строки на основе другого значения строки с определенным условием, панды

#python #pandas #dataframe

Вопрос:

Я пытаюсь сделать что-то подобное. У меня есть фрейм данных:

 list_val = {'Region': [3715, 3715, 3715, 3715, 3715, 3715, 3715, 3715, 3715, 3715, 3718, 3718, 3718],   'Category': [1, 1, 1, 1,1, 2, 2 ,2 ,2, 2,1 ,1 ,1],  'level': ['E', 'E/M', 'M', 'S', 'unknown', 'E', 'E/M', 'M', "S", "unknown", 'M', "E/M", 'unknown'],  'low': [2, 5, 10, 4, -1, 8, 12, 5, 14, -1, 3, 5, -1],  'high': [3, 6, 5, 6, -1, 12, 8, 9, 15, -1, 3, 8, -1]} df = pd.DataFrame(list_val) df  
 Region Category level low high 0 3715 1 E 2 3 1 3715 1 E/M 5 6 2 3715 1 M 10 5 3 3715 1 S 4 6  4 3715 1 unknown -1 -1  5 3715 2 E 8 12 6 3715 2 E/M 12 8 7 3715 2 M 5 9 8 3715 2 S 14 15  9 3715 2 unknown -1 -1  10 3718 1 M 3 3 11 3718 1 E/M 5 8  12 3718 1 unknown -1 -1   

Я пытаюсь заполнить столбец «низкий» уровнем «неизвестный», т. е. -1 значением «низкий», где уровень «E», т. е. 2, и значением «высокий», с уровнем «неизвестный», т. е. -1 значением «высокий», где уровень «S», т. е. 6 и так далее для каждой категории и каждого региона. И если для любого региона и категории отсутствует уровень » E » или «S», сохраняйте низкое и высокое значение только как -1. Итак, чего я хочу, так это:

 Region Category level low high 0 3715 1 E 2 3 1 3715 1 E/M 5 6 2 3715 1 M 10 5 3 3715 1 S 4 6  4 3715 1 unknown 2 6  5 3715 2 E 8 12 6 3715 2 E/M 12 8 7 3715 2 M 5 9 8 3715 2 S 14 15  9 3715 2 unknown 8 15  10 3718 1 M 3 3 11 3718 1 E/M 5 8 12 3718 1 unknown -1 -1   

Я пробовал разные способы, но ничто не дает того, чего я хочу, последнее, что я пробовал, — это:

 for index in df.index:  if df.loc[index,'level'] == 'Unknown':  df.loc[index,'low'] = df['low'].where(df['level'] == 'E')  df.loc[index, 'high'] = df['high'].where(df['level] == 'S')  

но это приводит к ошибкам. Не мог бы кто-нибудь, пожалуйста, подсказать, как мне это сделать? Спасибо!

Ответ №1:

Используйте loc обновление с map/replace :

 e_val = df.loc[df['level']=='E'].set_index(['Region', 'Category'])['low']  # use `lower` since there is `unknown` and `Unknown` unknowns = df['level'].str.lower() == 'unknown' df.loc[unknowns, 'low'] = (df.loc[unknowns, ['Region','Category']]  .agg(tuple,axis=1)  .map(e_val)  )  

Выход:

 Region Category level low high 0 3715 1 E 2.0 3 1 3715 1 E/M 5.0 6 2 3715 1 M 10.0 5 3 3715 1 S 4.0 6 4 3715 1 unknown 2.0 -1 5 3715 2 E 8.0 12 6 3715 2 E/M 12.0 8 7 3715 2 M 5.0 9 8 3715 2 S 14.0 15 9 3715 2 unknown 8.0 -1 10 3718 1 M 3.0 3 11 3718 1 E/M 5.0 8 12 3718 1 unknown NaN -1  

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

1. Привет, Куанг, большое тебе спасибо. У меня есть следующий вопрос, что делать, если у нас много регионов, таких как 3715, 3718,….. и т.д., И в каждом регионе много категорий, как здесь, в регионе 3715 есть категории 1 и 2. и мы хотим рассчитать одно и то же для каждого региона, каждой категории. Какие изменения я должен внести? Я добавил регион в строке 1: e_val = df.loc[df['level']=='E'].set_index('Region', 'Category')['low'] как соответствующим образом изменить последнюю строку?

2. Привет, Куанг, я обновил свой вопрос для большей ясности!

3. Перед этим вам необходимо объединить пары ключей в кортежи map . см.Отредактированный ответ.

4. Спасибо тонне Куанг. Работает отлично!