Python中如何将树状图转树对象并关联叶节点标签?
Hey there! Let's work through how to connect each ClusterNode (from SciPy's to_tree() method) to the positions in den['leaves'] and labels in den['ivl'] for your hierarchical text clustering. Here's a straightforward, step-by-step breakdown:
First, let's generate the root node of your cluster tree using the linkage matrix you created:
from scipy.cluster.hierarchy import to_tree # Convert your linkage matrix `l` into a ClusterNode root object root = to_tree(l)
The den['leaves'] list holds the original indices of your leaf nodes (matching the order in model.wv.index2word) as they appear in the dendrogram. den['ivl'] is the corresponding list of labels in that same dendrogram order. We'll create two dictionaries to bridge these values:
# Map leaf node ID → its position index in den['leaves'] leaf_id_to_pos = {leaf_id: idx for idx, leaf_id in enumerate(den['leaves'])} # Map leaf node ID → its label from den['ivl'] # (This is the same as model.wv.index2word[leaf_id], but uses den['ivl'] directly) leaf_id_to_label = {den['leaves'][idx]: label for idx, label in enumerate(den['ivl'])}
We can write a recursive traversal function to walk the tree, linking leaf nodes to their dendrogram positions and labels, while tracking how internal nodes merge child clusters.
Basic Depth-First Traversal (Post-Order)
This aligns with the order clusters were merged, and matches the structure of den['leaves']:
def traverse_tree(node, id_to_pos, id_to_label): # Handle leaf nodes (link to dendrogram position and label) if node.is_leaf(): pos = id_to_pos[node.id] label = id_to_label[node.id] print(f"Leaf Node: ID={node.id} | Dendrogram Position={pos} | Label='{label}'") return { "type": "leaf", "id": node.id, "dendrogram_pos": pos, "label": label } # Handle internal nodes (track merged child clusters) else: left_child = traverse_tree(node.left, id_to_pos, id_to_label) right_child = traverse_tree(node.right, id_to_pos, id_to_label) print(f"Internal Node: ID={node.id} | Merged Nodes={node.left.id} & {node.right.id}") return { "type": "internal", "id": node.id, "left_child": left_child, "right_child": right_child } # Start traversal from the root node tree_structure = traverse_tree(root, leaf_id_to_pos, leaf_id_to_label)
Advanced Traversal (Track All Leaves in Internal Nodes)
If you want each internal node to include details of all leaf nodes it contains (with their positions and labels), use this modified function:
def traverse_tree_with_leaf_details(node, id_to_pos, id_to_label): if node.is_leaf(): pos = id_to_pos[node.id] label = id_to_label[node.id] leaf_details = [{ "leaf_id": node.id, "dendrogram_pos": pos, "label": label }] return { "type": "leaf", "id": node.id, "leaves": leaf_details } else: left_leaves = traverse_tree_with_leaf_details(node.left, id_to_pos, id_to_label)["leaves"] right_leaves = traverse_tree_with_leaf_details(node.right, id_to_pos, id_to_label)["leaves"] all_leaves = left_leaves + right_leaves print(f"Internal Node {node.id} contains {len(all_leaves)} leaves: {[leaf['label'] for leaf in all_leaves]}") return { "type": "internal", "id": node.id, "left_child_id": node.left.id, "right_child_id": node.right.id, "leaves": all_leaves } tree_with_leaves = traverse_tree_with_leaf_details(root, leaf_id_to_pos, leaf_id_to_label)
- A
ClusterNode'sidattribute: For leaf nodes, this is the original index from your word vectors (matchesmodel.wv.index2word). For internal nodes, IDs start atn(wherenis the number of original samples) and increment as clusters are merged. den['leaves']order: This is the sequence of leaf nodes as they appear in your left-oriented dendrogram (top to bottom). Our mapping dictionaries let you directly link this position to the leaf's ID and label.
内容的提问来源于stack exchange,提问作者Christina Tsangouri

