Другой подход, использующий from_pandas_edgelist
и ancestors
из пакета networkx
:
import networkx as nx
# Create the Directed Graph
G = nx.from_pandas_edgelist(df,
source='Parent',
target='child',
create_using=nx.DiGraph())
# Create dict of nodes and ancestors
ancestors = {n: {n} | nx.ancestors(G, n) for n in df['child'].unique()}
# Convert dict back to DataFrame if necessary
df_ancestors = pd.DataFrame([(k, list(v)) for k, v in ancestors.items()],
columns=['node', 'ancestry_tree'])
print(df_ancestors)
[ out]
node ancestry_tree
0 A1x2 [A1x2, Aw00, bc11]
1 bc11 [bc11, Aw00]
2 Aee1 [Aee1, Aee0]
Чтобы отфильтровать «промежуточных детей» из выходной таблицы, вы можете отфильтровать по последним дочерним элементам только с помощью метода out_degree
- там, где последние дочерние элементы должны иметь выходную степень == 0
last_children = [n for n, d in G.out_degree() if d == 0]
ancestors = {n: {n} | nx.ancestors(G, n) for n in last_children}
df_ancestors = pd.DataFrame([(k, list(v)) for k, v in ancestors.items()],
columns=['node', 'ancestry_tree'])
[out]
node ancestry_tree
0 A1x2 [A1x2, Aw00, bc11]
1 Aee1 [Aee1, Aee0]