基于Pyviz实现多关联规则子图合并与交互式筛选的技术问询
基于Pyviz实现多关联规则子图合并与交互式筛选的技术问询
嘿,我完全get到你的需求了——把多组关联规则的子图合并成一个完整的网络图,然后通过下拉菜单切换查看特定子图对吧?这其实可以通过给每个子图的节点和边打上分组标签,再借助Pyviz自带的筛选功能轻松实现,下面是具体的思路和修改后的代码:
核心实现思路
- 为每个子图的所有节点和边添加一个分组标识属性(比如
group),分别标记为graph_1、graph_2、graph_3,作为后续筛选的依据 - 将三个子图合并到同一个NetworkX有向图中,完整保留所有节点和边的属性信息
- 利用Pyviz的
filter_menu功能,自动识别分组属性生成下拉筛选菜单,实现子图的切换显示
修改后的代码实现
import networkx as nx import numpy as np from pyvis.network import Network def build_grouped_graph(rules, group_name): rules_to_show = len(rules) G = nx.DiGraph() strs = [] median = rules['confidence'].median() # 遍历规则构建带分组属性的节点和边 for i in range(rules_to_show): conf = rules.iloc[i]['confidence'] # 给规则节点加分组后缀,避免不同子图的规则节点重名 rule_node = f"R{i}_{group_name}" strs.append(rule_node) # 给节点添加group属性 G.add_node(rule_node, group=group_name) # 处理前件节点与边 for a in rules.iloc[i]['antecedents']: if a not in G: G.add_node(a, group=group_name) edge_color = 'lightgrey' if conf > median else 'orange' # 给边也添加group属性 G.add_edge(a, rule_node, color=edge_color, value=conf*0.01, group=group_name) # 处理后件节点与边 for c in rules.iloc[i]['consequents']: if c not in G: G.add_node(c, group=group_name) edge_color = 'lightgrey' if conf > median else 'orange' G.add_edge(rule_node, c, color=edge_color, value=conf*0.01, group=group_name) # 生成节点颜色映射(保留你原来的逻辑) color_map = [] for node in G: if node in strs: color_map.append("lightblue") else: color_map.append("lightgreen") return G, color_map # ---------------------- 假设你有三个规则数据集 ---------------------- # rules_df1, rules_df2, rules_df3 分别对应三组关联规则数据 # dataset1, dataset2, dataset3 分别对应三组数据的支持度信息 # ----------------------------------------------------------------- # 构建三个带分组属性的子图 graph1, color_map1 = build_grouped_graph(rules_df1, "graph_1") graph2, color_map2 = build_grouped_graph(rules_df2, "graph_2") graph3, color_map3 = build_grouped_graph(rules_df3, "graph_3") # 合并三个子图到总网络图中 total_graph = nx.DiGraph() # 合并节点(保留属性) total_graph.add_nodes_from(graph1.nodes(data=True)) total_graph.add_nodes_from(graph2.nodes(data=True)) total_graph.add_nodes_from(graph3.nodes(data=True)) # 合并边(保留属性) total_graph.add_edges_from(graph1.edges(data=True)) total_graph.add_edges_from(graph2.edges(data=True)) total_graph.add_edges_from(graph3.edges(data=True)) # 合并颜色映射,确保每个节点对应正确颜色 all_color_map = {} for node, color in zip(graph1.nodes, color_map1): all_color_map[node] = color for node, color in zip(graph2.nodes, color_map2): all_color_map[node] = color for node, color in zip(graph3.nodes, color_map3): all_color_map[node] = color sorted_color_map = [all_color_map[node] for node in total_graph.nodes] # 处理节点大小(基于支持度,保留你原来的逻辑) mydic = {} for dataset in [dataset1, dataset2, dataset3]: for index, row in dataset.iterrows(): mydic[row["items"]] = row['support'] node_values = [] for node in total_graph.nodes: node_values.append(int(mydic.get(node, 0.0001)*10000)) # 生成Pyviz交互式可视化 nt = Network(notebook=True, cdn_resources="remote", bgcolor="#222222", font_color="white", height="750px", width="100%", select_menu=True, filter_menu=True) # 开启筛选菜单,自动识别group属性 # 添加节点,包含大小、颜色和分组属性 for idx, node in enumerate(total_graph.nodes): nt.add_node(node, value=node_values[idx], color=sorted_color_map[idx], group=total_graph.nodes[node]['group']) # 添加边,保留原有的颜色和权重属性 for edge in total_graph.edges(data=True): nt.add_edge(edge[0], edge[1], color=edge[2]['color'], value=edge[2]['value'], group=edge[2]['group']) # 设置物理布局和显示控制按钮 nt.repulsion(node_distance=100, spring_length=500) nt.show_buttons(filter_=['physics']) # 保存并打开可视化页面 nt.show('combined_association_rules.html')
代码关键点说明
- 分组子图构建:
build_grouped_graph函数专门生成带分组属性的子图,给规则节点加分组后缀避免重名,同时给每个节点和边都打上group标签 - 子图合并:完整合并三个子图的节点和边,保留所有属性信息,确保总网络图包含全部数据
- 筛选功能启用:开启Pyviz的
filter_menu后,页面会自动生成基于group属性的下拉菜单,你可以选择只显示graph_1、graph_2或graph_3的内容 - 原有逻辑保留:完全保留了你原来的节点颜色规则(规则节点浅蓝色、项节点浅绿色)和支持度转节点大小的逻辑
注意事项
如果不同子图中有相同的项节点(比如多个子图都包含牛奶这个节点),上面的代码会让这个节点只属于最后添加的子图分组。如果希望共享节点在选中任意分组时都显示,可以修改节点的group属性为列表(比如["graph_1", "graph_2"]),不过Pyviz默认的筛选菜单是精确匹配,这时候可能需要自定义筛选逻辑,或者给共享节点添加多个分组标签(比如"graph_1|graph_2")后用模糊匹配。
备注:内容来源于stack exchange,提问作者rooya sh
相关产品推荐
相关产品推荐

