从图中创建一棵树结构

3
我试图找到正确的方法来绘制包含用户在各个位置通常花费时间信息的数据集的图表。重要的是,我的数据有类别和子类别,具有逐渐增加的细粒度(例如,60%的人在“家中”,其中40%在“客厅”)。我知道TreeMaps可以显示我需要的信息和关系,但我被要求制作一种数据的“网络”可视化。
我特别寻找的是Python中的一种绘图方法,它可以让我按照落入其类别的用户数量自动调整节点(最好是节点标签)的大小来可视化我的数据。重要的是,所有子节点计数也将计入父节点中(因此树状图并不是一个选项,因为我需要在每个分支点上显示信息)。
我的数据看起来有点像这样(请注意,某些位置比其他位置更细粒度):
| ID | BUILDING | subcat01  | subcat02 |
----------------------------------------
| 00 |  home    | kitchen   | fridge   |
| 01 |  office  | desk      | NaN      |
| 02 |  office  | reception | NaN      |
| 03 |  home    | bedroom   | bed      |
| 04 |  home    | yard      | NaN      |
| 05 |  home    | livingroom| couch    |
| 06 |  office  | conf_room | NaN      |
| 07 | outdoors | NaN       | NaN      |
|... | ...      | ...       | ...      |

为了大致实现我想要的效果,请参见下面的图像。重要的是,我能够根据它们的子节点之和(或者仅仅是它们自己,如果它是一个末端节点)来调整节点的大小。我将运行许多不同过滤器的迭代,因此我需要一些可以轻松迭代的东西,而不仅仅是手动编写每个图形的外观。
有哪些Python库可能最好地实现这一点?我简要地研究了networkXgraph-tooletetoolkit,但我不确定它们是否具有我正在寻找的确切功能。
这是我想制作的粗略近似:

enter image description here

2个回答

4

要生成图表,您可以将行设置为有向图的路径。一种简单的方法是定义一个 pandas 数据帧并堆叠以删除缺失值:

import networkx as nx
from networkx.drawing.nx_agraph import graphviz_layout
from pylab import rcParams
import pandas as pd
#df = pd.read_csv....
paths = df.loc[:,'BUILDING':].stack().groupby(level=0).agg(list).values.tolist()  
# [['home', 'kitchen', 'fridge'], ['office', 'desk'], ['office', 'reception'],...

请注意,由于堆栈忽略NaN值,因此在索引上进行groupby并聚合为列表非常有用。 然后创建一个有向图并使用nx.add_path设置路径:
G = nx.DiGraph()
for path in paths:
    nx.add_path(G, path)

现在要将图形可视化为类似树状的布局,我们可以使用graphviz_layout,它基本上是pygraphviz_layout的包装器。请注意保留HTML标记。
rcParams['figure.figsize'] = 14, 10
pos=graphviz_layout(G, prog='dot')
nx.draw(G, pos=pos,
        node_color='lightgreen', 
        node_size=1500,
        with_labels=True, 
        arrows=True)

enter image description here

如果你想为所有建筑物添加一个共同的来源节点,你可以在ID列之后插入一个名为ALL的列:

df.insert(1, 'ALL', 'ALL')
paths = df.loc[:,'ALL':].stack().groupby(level=0).agg(list).values.tolist()  

然后按照上述步骤进行操作,您现在会得到:

enter image description here

请注意,还有其他几个graphviz布局程序可能更符合您的要求。例如circo

pos=graphviz_layout(G, prog='circo')
nx.draw(G, pos=pos,
        node_color='lightgreen', 
        node_size=1500,
        with_labels=True, 
        arrows=True)

enter image description here


好的解决方案,有没有关于为每个级别(“building”,“subcat1”等)添加描述的想法? - Андрей Севостьянов

0

也许 ETE 包可以帮助你。ETE 是一个 Python 包,旨在实现程序化树形渲染和可视化等功能。

enter image description here


但是似乎不适合Windows用户? - Mark K

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接