Python中基于Pandas DataFrame绘制树状图的技术疑问及求解
解决从Pandas DataFrame绘制网络通信树状图的问题
首先,咱们得先把你的数据转换成树结构需要的层级格式,再选合适的工具来可视化。你的数据包含source(源IP)、destination(目标IP)、application(应用)和timemark(时间戳),要构建的树层级应该是:Source → Destination → Application(如果需要,还可以把timemark作为节点的附加信息)。
步骤1:数据预处理(清洗与分组)
首先得对DataFrame做分组和去重,避免重复节点。比如同一对source-destination下可能有多个相同的application记录(不同时间戳),可以先按source、destination、application分组,保留唯一组合,或者把timemark聚合起来(比如收集所有时间戳、统计通信次数)。
假设你的DataFrame叫df,先做预处理:
import pandas as pd # 示例数据(模拟你的数据集) data = { 'source': ['192.168.1.1', '192.168.1.1', '192.168.1.2', '192.168.1.1'], 'destination': ['192.168.1.200', '192.168.1.200', '192.168.1.100', '192.168.1.300'], 'application': ['ping', 'http', 'ssh', 'ping'], 'timemark': ['10:00AM', '10:05AM', '10:10AM', '10:15AM'] } df = pd.DataFrame(data) # 按source→destination→application分组,聚合timemark(收集所有时间戳) grouped_df = df.groupby(['source', 'destination', 'application'])['timemark'].agg(list).reset_index()
步骤2:构建树结构
这里推荐用treelib库来快速构建层级树,它能方便地创建节点、管理父子关系,还支持文本和图形化输出。
先安装treelib:
pip install treelib
然后编写构建树的代码:
from treelib import Tree # 创建总根节点(可选,用来统管所有source节点) tree = Tree() tree.create_node("Network Traffic", "root") # 遍历分组后的数据,逐层添加节点 for idx, row in grouped_df.iterrows(): source = row['source'] dest = row['destination'] app = row['application'] times = ', '.join(row['timemark']) # 检查source节点是否存在,不存在则创建 if not tree.contains(source): tree.create_node(source, source, parent="root") # 检查destination节点是否属于当前source,不存在则创建 dest_node_id = f"{source}_{dest}" if not tree.contains(dest_node_id): tree.create_node(dest, dest_node_id, parent=source) # 添加application节点,附带时间戳信息 app_node_id = f"{dest_node_id}_{app}" tree.create_node(f"{app} (times: {times})", app_node_id, parent=dest_node_id) # 先打印文本形式的树,快速验证结构 tree.show()
运行后会输出清晰的文本树结构,比如:
Network Traffic ├── 192.168.1.1 │ ├── 192.168.1.200 │ │ ├── ping (times: 10:00AM) │ │ └── http (times: 10:05AM) │ └── 192.168.1.300 │ └── ping (times: 10:15AM) └── 192.168.1.2 └── 192.168.1.100 └── ssh (times: 10:10AM)
步骤3:图形化树状图展示
如果需要可视化的树状图,可以用以下两种方法:
方法1:用treelib导出为图片(需安装graphviz)
先安装依赖:
pip install graphviz
然后导出并生成图片:
# 导出为dot格式文件 tree.to_graphviz("network_tree.dot") # 把dot文件转成png图片 from graphviz import render render('dot', 'png', 'network_tree.dot')
执行后会生成network_tree.png,展示标准的树形层级图。
方法2:用NetworkX + Matplotlib绘制交互式树
如果更习惯用matplotlib,可以用NetworkX构建图结构,再绘制树形布局:
import networkx as nx import matplotlib.pyplot as plt G = nx.DiGraph() # 逐层添加节点和边 for idx, row in grouped_df.iterrows(): source = row['source'] dest = row['destination'] app = row['application'] app_label = f"{app}\n({', '.join(row['timemark'])})" # 添加总根节点 if 'root' not in G.nodes: G.add_node('root', label='Network Traffic') G.add_edge('root', source) # 添加source到dest的边 G.add_edge(source, dest) # 添加dest到application的边 G.add_edge(dest, app_label) # 设置树形布局(用graphviz的dot布局) pos = nx.nx_agraph.graphviz_layout(G, prog='dot') # 绘制节点和边 nx.draw(G, pos, with_labels=True, node_size=3500, node_color='lightblue', font_size=8, arrows=True) plt.title("Network Communication Tree") plt.show()
方法3:交互式树形图(Plotly)
如果需要可交互的探索式树图(比如点击节点展开/折叠),可以用Plotly的treemap或sunburst:
import plotly.express as px # 构造Plotly需要的层级路径数据 plot_df = grouped_df.copy() plot_df['count'] = plot_df['timemark'].apply(len) # 统计每个通信组合的次数 fig = px.treemap(plot_df, path=['source', 'destination', 'application'], values='count', hover_data={'timemark': plot_df['timemark'].apply(', '.join)}) fig.update_layout(title="Network Communication Treemap") fig.show()
注意事项
- 如果数据量很大,树状图会拥挤,建议过滤低频通信对,或者合并重复节点。
- timemark可以按需处理:比如只保留最新/最早时间,或者统计通信次数,作为节点标签的一部分。
内容的提问来源于stack exchange,提问作者Pablo Ibañez Matía
相关产品推荐
相关产品推荐

