Дублирование строк в фрейме данных Pandas и замена значений несколькими другими значениями

#python #pandas #dataframe

Вопрос:

Прежде всего, всем привет! Это первый раз, когда я на самом деле публикую вопрос в StackOverflow, поэтому, если я слишком конкретен / слишком общий, я был бы признателен за совет :).

У меня есть фрейм данных Pandas, содержащий некоторые данные авторизации SAP, в котором столбец может содержать что-то вроде «значений-заполнителей», которые должны быть преобразованы в соответствующие им значения. И на данный момент у меня действительно закончились идеи..

Например, в фрейме данных, показанном ниже, у меня есть две роли, каждая из которых содержит объект (авторизации) F_BKPF_BUK с полями ACTVT и ABC . ABC характеризуется «значением-заполнителем» $EKGRP для LOW .

                    ROLE        OBJECT    FIELD     LOW HIGH
0  D:AS:MY_FANCY_ROLE_A    F_BKPF_BUK    ACTVT      03  NaN
1  D:AS:MY_FANCY_ROLE_A    F_BKPF_BUK      ABC  $EKGRP  NaN
2  D:AS:MY_FANCY_ROLE_B    F_BKPF_BUK    ACTVT      03  NaN
3  D:AS:MY_FANCY_ROLE_B    F_BKPF_BUK      ABC  $EKGRP  NaN
 

Теперь сложность в том, что заполнитель $EKGRP обычно преобразуется в зависящие от роли (!) множественные значения. Фрейм данных для $EKGRP выглядит следующим образом:

                    ROLE   VARBL  LOW HIGH
0  D:AS:MY_FANCY_ROLE_A  $EKGRP  U01  U99
1  D:AS:MY_FANCY_ROLE_A  $EKGRP  P01  P99
2  D:AS:MY_FANCY_ROLE_A  $EKGRP  P01  P29
3  D:AS:MY_FANCY_ROLE_B  $EKGRP  P01  P00
4  D:AS:MY_FANCY_ROLE_B  $EKGRP  N01  N99
5  D:AS:MY_FANCY_ROLE_B  $EKGRP  I01  I99
 

Итак, конечный результат, которого я хотел бы достичь, — заменить все вхождения заполнителя соответствующими значениями для обоих столбцов LOW и HIGH :

                    ROLE        OBJECT    FIELD     LOW HIGH
0  D:AS:MY_FANCY_ROLE_A    F_BKPF_BUK    ACTVT      03  NaN
1  D:AS:MY_FANCY_ROLE_A    F_BKPF_BUK      ABC     U01  U99
2  D:AS:MY_FANCY_ROLE_A    F_BKPF_BUK      ABC     P01  P99
3  D:AS:MY_FANCY_ROLE_A    F_BKPF_BUK      ABC     P01  P29
4  D:AS:MY_FANCY_ROLE_B    F_BKPF_BUK    ACTVT      03  NaN
5  D:AS:MY_FANCY_ROLE_B    F_BKPF_BUK      ABC     P01  P00
6  D:AS:MY_FANCY_ROLE_B    F_BKPF_BUK      ABC     N01  N99
7  D:AS:MY_FANCY_ROLE_B    F_BKPF_BUK      ABC     I01  I99
 

Начал использовать Pandas всего несколько недель назад, вскоре я достиг точки, когда у меня закончились идеи для этой конкретной проблемы. Мое последнее предположение состояло в том, чтобы, возможно, использовать df.apply(...) для проверки наличия заполнителя, но этот подход не решит проблему, заключающуюся в том, что после нахождения заполнителя исходная строка должна быть продублирована несколько раз, а их LOW HIGH значения и будут изменены на соответствующие значения.
На какую функцию pandas вы бы порекомендовали мне взглянуть поближе? Я хотел бы, насколько это возможно, избегать итераций по строкам и ознакомиться с «лучшими практиками» для такого рода проблем.

Ответ №1:

Если возможно, используйте внешнее соединение по столбцу LOW from df1 с ROLE первой копией LOW в VARBL in DataFrame.assign , затем замените отсутствующие значения в DataFrame.fillna (необходимо удалить _ в столбцах для соответствия) и в последний раз удалите ненужные столбцы:

 df = (df1.assign(VARBL = df1['LOW'])
         .merge(df2, on=['ROLE','VARBL'], how='outer', suffixes=('_','')))

df[['LOW','HIGH']] = (df[['LOW','HIGH']].fillna(df[['LOW_','HIGH_']]
                                                  .rename(columns=lambda x: x.strip('_'))))
df = df.drop(['LOW_','HIGH_','VARBL'], axis=1)
print (df)
                   ROLE      OBJECT  FIELD  LOW HIGH
0  D:AS:MY_FANCY_ROLE_A  F_BKPF_BUK  ACTVT   03  NaN
1  D:AS:MY_FANCY_ROLE_A  F_BKPF_BUK    ABC  U01  U99
2  D:AS:MY_FANCY_ROLE_A  F_BKPF_BUK    ABC  P01  P99
3  D:AS:MY_FANCY_ROLE_A  F_BKPF_BUK    ABC  P01  P29
4  D:AS:MY_FANCY_ROLE_B  F_BKPF_BUK  ACTVT   03  NaN
5  D:AS:MY_FANCY_ROLE_B  F_BKPF_BUK    ABC  P01  P00
6  D:AS:MY_FANCY_ROLE_B  F_BKPF_BUK    ABC  N01  N99
7  D:AS:MY_FANCY_ROLE_B  F_BKPF_BUK    ABC  I01  I99