Полное раскрытие: я задал похожий вопрос в Code Review , но не получил никакой обратной связи с использованием панд, и я хотел быть более конкретным.
У меня есть DataFrameудерживая «плоскую» таблицу ребер дерева (НЕ двоичную, но узел не может иметь двух родителей), ребра ~ 1M, см. пример:
import pandas as pd
nodes_df = pd.DataFrame({'node_id': [1,2,3,4,5,6,7,8,9,10], 'parent_id': [0,1,1,2,2,3,4,5,6,6]})
nodes_df
node_id parent_id
0 1 0
1 2 1
2 3 1
3 4 2
4 5 2
5 6 3
6 7 4
7 8 5
8 9 6
9 10 6
Узлы отсортированы таким образом, что parent_idвсегда должен предшествовать любому из его потомков, поэтому parent_id всегда будет ниже, чем node_id.
Я хочу, чтобы для каждого node_id был получен набор всех узлов-потомков (включая самого себя, распространяемых до тех пор, пока не уйдет), искорость имеет решающее значение.Я говорю «установить», потому что это то, что я делаю в настоящее время (см. Ниже).Но даже более длинная таблица, полученная в результате манипуляций с пандами (node_id, lowerndant_node_id), тоже подойдет.
В настоящее время я создаю словарь из node_id для набора всех его потомков, например:
from collections import defaultdict
node_descendants = defaultdict(set)
node_descendants[0] = set([0])
for _, node_id, parent_id in nodes_df[::-1].itertuples():
node_descendants[node_id].add(node_id)
node_descendants[parent_id].update(node_descendants[node_id])
node_descendants
defaultdict(<class 'set'>, {0: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 10: {10}, 6: {9, 10, 6}, 9: {9}, 8: {8}, 5: {8, 5}, 7: {7}, 4: {4, 7}, 3: {9, 10, 3, 6}, 2: {2, 4, 5, 7, 8}, 1: {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}})
Есть ли какой-нибудь способ, которым я мог бы использовать силу панд для этого, с join
s и groupby
s?Желательно намного быстрее (помните, у меня ~ 1M ребер или узлов, а не 10)