Построение иерархии с помощью Python
Прошу помочь в решении следующей задачи.
В упрощенном виде: есть таблица вида
| таб номер подч | подчиненный | таб номер рук | руководитель |
|---|---|---|---|
| 112233 | Ген. дер. | 123344456 | Вице-президент |
| 113213 | Гл. экономист | 112233 | Ген. дер. |
| 114213 | специалист | 112233 | Ген. дер. |
| 212233 | Слесарь | 12334 | Мастер |
| 353213 | Электрик | 12334 | Мастер |
| 12334 | Мастер | 45678 | Нач. цеха 1 |
| ... | ... | ... | ... |
и т.д.
Всего записей в таблице порядка 117 тыс. строк.
Мне нужно вывести с помощью Python новую графу "верхнеуровневую подчиненность" в таблицу для дальнейшей группировки. Эта графа отражает верхнеуровневого руководителя
Что должно получиться:
| таб номер подч | подчиненный | таб номер рук | руководитель | верхнеур. подчиненность |
|---|---|---|---|---|
| 112233 | Ген. дер. | 123344456 | Вице-президент | Вице-президент |
| 113213 | Гл. экономист | 112233 | Ген. дер. | Вице-президент |
| 114213 | специалист | 112233 | Ген. дер. | Вице-президент |
| 212233 | Слесарь | 12334 | Мастер | Нач. цеха 1 |
| 353213 | Электрик | 12334 | Мастер | Нач. цеха 1 |
| 12334 | Мастер | 45678 | Нач. цеха 1 | Нач. цеха 1 |
| ... | ... | ... | ... | ... |
и т.д.
Уровней "вхождения" в иерархию достаточно много. Здесь в примере указано 2 уровня вхождения для каждой из групп: Вице-президент и ген. директор, а также для второй группы Нач. цеха 1 и мастер. Уровни подчинения определяются следующим образом, например, если главный экономист и специалист подчинены генеральному директору, а тот, в свою очередь, подчиняется Вице-президенту, то и главный экономист и специалист также подчиняются Вице-президенту, поэтому напротив них в графе верхнеур. подчиненность должно стоять Вице-президент.
Использую такой код на Python:
df['верхнеур. подчиненность'] = df['таб номер рук'].map(df.set_index('таб номер подч')['подчиненный'])
Но получаю столбец, дублирующий поле руководитель. Прошу подсказать, как доработать/изменить код и решить задачу.
Ответы (1 шт):
Суть преобразования - объединить фрейм с самим собой, сопоставив поля "руководитель" и "подчиненный" и взяв в целевое поле "руководителя руководителя".
Так, например "руководитель" "Ген. дер." сопоставляется с "подчиненный" "Ген. дер.", у которого забирается в целевое поле "руководитель" - "Вице-президент".
Поскольку высшие руководители не встречаются в поле "подчиненный", у них в целевом поле возникает NaN, который просто заполняется их руководителем, т.е. своей же должностью.
import pandas as pd
df = pd.DataFrame({'таб номер подч': [112233, 113213, 114213, 212233, 353213, 12334], 'подчиненный': ['Ген. дер.', 'Гл. экономист', 'специалист', 'Слесарь', 'Электрик', 'Мастер'],
'таб номер рук': [123344456, 112233, 112233, 12334, 12334, 45678], 'руководитель': ['Вице-президент', 'Ген. дер.', 'Ген. дер.', 'Мастер', 'Мастер', 'Нач. цеха 1']})
df = (df.merge(df[['подчиненный', 'руководитель']], left_on='руководитель', right_on='подчиненный', how='left', suffixes=('', '_1'))
.rename(columns={'руководитель_1': 'верхнеур. подчиненность'}).drop(columns='подчиненный_1'))
df['верхнеур. подчиненность'] = df['верхнеур. подчиненность'].fillna(df['руководитель'])
print(df)
таб номер подч подчиненный таб номер рук руководитель верхнеур. подчиненность
0 112233 Ген. дер. 123344456 Вице-президент Вице-президент
1 113213 Гл. экономист 112233 Ген. дер. Вице-президент
2 114213 специалист 112233 Ген. дер. Вице-президент
3 212233 Слесарь 12334 Мастер Нач. цеха 1
4 353213 Электрик 12334 Мастер Нач. цеха 1
5 12334 Мастер 45678 Нач. цеха 1 Нач. цеха 1