基于交易数据的用户-应用交互式网络可视化优化需求
优化方案:交互式员工-应用访问网络图(边尺寸随传输量动态调整)
核心思路
基于你的需求,推荐两种成熟的实现路径:轻量快速的Pyvis方案,或高度定制化的Plotly+NetworkX方案,两者都能满足节点贴近关联对象、边宽随交易总量变化、交互式操作三个核心要求。
先明确预处理前提
如果你的原始数据存在重复的「员工-应用」记录,先聚合计算总传输量,避免重复边:
import pandas as pd # 假设你的数据存放在data.csv中 df = pd.read_csv("data.csv") # 按员工邮箱+应用分组,求和得到总传输量 agg_df = df.groupby(["员工邮箱", "访问应用"])["交易数据传输量"].sum().reset_index()
方案1:Pyvis(快速实现交互式)
Pyvis是专门用于交互式网络图的库,支持拖拽、缩放、悬停显示信息,代码量极少。
安装依赖
pip install pyvis pandas
完整代码
from pyvis.network import Network import pandas as pd # 示例数据(替换为你的聚合后数据) agg_df = pd.DataFrame([ {"员工邮箱": "alice@company.com", "访问应用": "AppA", "交易数据传输量": 1200}, {"员工邮箱": "bob@company.com", "访问应用": "AppA", "交易数据传输量": 800}, {"员工邮箱": "alice@company.com", "访问应用": "AppB", "交易数据传输量": 500}, {"员工邮箱": "charlie@company.com", "访问应用": "AppC", "交易数据传输量": 2000}, ]) # 初始化网络图,配置物理布局(让关联节点自动贴近) net = Network( height="800px", width="100%", bgcolor="#222", font_color="#fff", directed=False # 无向图,符合访问关系 ) # 调整布局参数:spring_length越小,关联节点距离越近;gravity控制整体紧凑度 net.barnes_hut(gravity=-7000, spring_length=150, spring_strength=0.02) # 添加节点与边 for _, row in agg_df.iterrows(): user_node = row["员工邮箱"] app_node = row["访问应用"] traffic = row["交易数据传输量"] # 区分节点样式:用户节点绿色,应用节点蓝色 if user_node not in [n["id"] for n in net.nodes]: net.add_node(user_node, color="#0f0", size=20, title=f"用户: {user_node}") if app_node not in [n["id"] for n in net.nodes]: net.add_node(app_node, color="#00f", size=30, title=f"应用: {app_node}") # 边宽按传输量缩放(系数根据你的数据最大值调整,保证边宽在1-20区间) edge_width = traffic / 200 net.add_edge( user_node, app_node, width=edge_width, title=f"总传输量: {traffic}" ) # 生成可直接打开的交互式HTML文件 net.show("employee_app_network.html")
关键调整点
- 修改
spring_length:值越小,访问同一应用的用户节点会越贴近该应用节点 - 调整
edge_width的缩放系数:如果你的最大传输量是10000,可改为traffic / 500,避免边过粗
方案2:Plotly + NetworkX(高度定制化)
如果需要更复杂的交互逻辑(比如点击节点展示详情、自定义图例),用Plotly配合NetworkX更灵活。
安装依赖
pip install plotly networkx pandas
完整代码
import networkx as nx import plotly.graph_objects as go import pandas as pd # 示例数据(替换为你的聚合后数据) agg_df = pd.DataFrame([ {"员工邮箱": "alice@company.com", "访问应用": "AppA", "交易数据传输量": 1200}, {"员工邮箱": "bob@company.com", "访问应用": "AppA", "交易数据传输量": 800}, {"员工邮箱": "alice@company.com", "访问应用": "AppB", "交易数据传输量": 500}, {"员工邮箱": "charlie@company.com", "访问应用": "AppC", "交易数据传输量": 2000}, ]) # 构建图结构 G = nx.Graph() for _, row in agg_df.iterrows(): G.add_edge( row["员工邮箱"], row["访问应用"], weight=row["交易数据传输量"] ) # 布局:spring_layout的k值越小,节点整体距离越近(关联节点会自然贴近) pos = nx.spring_layout(G, k=0.12, seed=42) # seed保证布局固定可复现 # 提取节点坐标与样式 node_x = [pos[node][0] for node in G.nodes()] node_y = [pos[node][1] for node in G.nodes()] node_colors = ["#0f0" if "@" in node else "#00f" for node in G.nodes()] # 区分用户/应用节点 node_text = [f"{node}<br>类型: {'员工' if '@' in node else '应用'}" for node in G.nodes()] # 处理边数据:按传输量调整宽度 edge_x, edge_y, edge_width, edge_text = [], [], [], [] for u, v, attrs in G.edges(data=True): x0, y0 = pos[u] x1, y1 = pos[v] edge_x.extend([x0, x1, None]) edge_y.extend([y0, y1, None]) edge_width.append(attrs["weight"] / 200) edge_text.append(f"传输量: {attrs['weight']}") # 绘制边 edge_trace = go.Scatter( x=edge_x, y=edge_y, line=dict(width=edge_width, color="#888"), hoverinfo="text", text=edge_text, mode="lines" ) # 绘制节点 node_trace = go.Scatter( x=node_x, y=node_y, mode="markers+text", text=[node.split("@")[0] if "@" in node else node for node in G.nodes()], # 简化显示 textposition="top center", hoverinfo="text", textfont=dict(size=10), marker=dict( color=node_colors, size=20, line=dict(color="#fff", width=2) ) ) # 配置图布局 fig = go.Figure( data=[edge_trace, node_trace], layout=go.Layout( title="员工-应用访问关系图", titlefont_size=18, showlegend=False, hovermode="closest", margin=dict(b=20, l=5, r=5, t=40), xaxis=dict(showgrid=False, zeroline=False, showticklabels=False), yaxis=dict(showgrid=False, zeroline=False, showticklabels=False), clickmode="event+select" # 支持点击节点触发后续逻辑 ) ) # 显示交互式图(或用fig.write_html导出HTML) fig.show()
关键调整点
- 替换
spring_layout为kamada_kawai_layout:该布局会让边的长度更均匀,关联节点的贴近效果更稳定 - 若需要添加点击事件,可通过
fig.update_layout(clickmode='event+select')结合Plotly的回调函数实现
额外优化建议
- 节点分组高亮:可以给同一部门的员工节点设置相同颜色,或给高频访问的应用节点设置更大尺寸
- 布局微调:如果节点数量较多,Pyvis可增大
gravity值,NetworkX可减小k值,让布局更紧凑 - 数据过滤:如果存在传输量极小的记录,可提前过滤(比如
agg_df = agg_df[agg_df["交易数据传输量"] > 100]),避免图中出现过多细边
内容的提问来源于stack exchange,提问作者SAL
相关产品推荐
相关产品推荐

