Преобразование списка парных сравнений в иерархическое представление (столбцы) с использованием pandas Python - PullRequest
1 голос
/ 31 января 2020

У меня есть набор данных следующей формы (около 8000 строк)

Employee ID | Manager ID
a | b
c | b
b | e
d | e
e | f

Я хотел бы преобразовать это в форму, где вся «связь» между сотрудником на самом низком уровне иерархии и отображаются все менеджеры на верхнем иерархическом уровне, а именно:

Employee ID | Manager ID 1 | Manager ID 2 | Manager ID 3
a | b | e | f
c | b | e | f
d | e | f

Какой самый эффективный способ вычислить это с использованием pandas в Python?

Ответы [ 2 ]

0 голосов
/ 31 января 2020

Это больше относится к теории графов и деревьев. Pandas не специализируется в этой области. Для такого рода вопросов более подходящим является networkx. Я предлагаю решение с использованием networkx. Вам нужно установить или pip networkx перед обработкой.

Создайте DiGraph из вашего кадра данных. Получить список leaves графика. Используйте понимание списка с shortest_path, чтобы получить списки узлов от каждого root до leaf

import networkx as nx

G = nx.from_pandas_edgelist(df, 'Employee ID', 'Manager ID', create_using=nx.DiGraph)
leaves = [node for node in G if G.out_degree(node)==0]
data   = [nx.shortest_path(G, node, leaf) for node in G if G.in_degree(node)==0 
                                               for leaf in leaves]
manager_cols = [f'Manager ID {i}' for i in range(1, df['Manager ID'].nunique()+1)]

df_final = pd.DataFrame(data, columns=['Employee ID', *manager_cols])

Out[371]:
  Employee ID Manager ID 1 Manager ID 2 Manager ID 3
0           a            b            e            f
1           c            b            e            f
2           d            e            f         None
0 голосов
/ 31 января 2020

Вот решение с numpy и numbers не так уж много с pandas и names, может быть, оно поможет вам всегда:

employee = np.array(['a', 'c', 'b', 'd', 'e', 'f'])  # Add 'f' as employee 
manager = np.array(['b', 'b', 'e', 'e', 'f', 'f'])   # with himself as manager

Получить номер устройства ( извините ) за каждого сотрудника:

manager_idx = np.array([np.where(employee == mng)[0] for mng in manager]).ravel()

L oop до конца иерархии

manager_idx_list = [manager_idx]
while True:
    new_manger_idx = manager_idx_list[-1][manager_idx]
    if all(new_manger_idx == manager_idx_list[-1]):
        break
    else:
        manager_idx_list.append(new_manger_idx)


manager_list = np.array([employee[mng_idx] for mng_idx in manager_idx_list]).T
# 'a': [['b' 'e' 'f']
# 'c':  ['b' 'e' 'f']
# 'b':  ['e' 'f' 'f']
# 'd':  ['e' 'f' 'f']
# 'e':  ['f' 'f' 'f']
# 'f':  ['f' 'f' 'f']]
...