Warm tip: This article is reproduced from serverfault.com, please click

python-从图创建树形结构

(python - Create a tree structure from a graph)

发布于 2020-04-14 14:21:19

我正在尝试找到一种正确的方法来绘制数据集的图形,该数据集包含有关用户通常在各个位置花费的时间量的信息。重要的是,有些类别和子类别的数据粒度越来越高(例如,60%的人在“家”,而其中40%的人在“客厅”)。我知道TreeMap可以显示所需的信息和关系,但是有人要求我对数据进行“网络”可视化。

我特别想寻找的是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,但是不确定它们是否具有我所要查找的功能。

这是我想要产生的大致结果:

在此处输入图片说明

Questioner
magnawhale
Viewed
0
yatu 2020-04-15 06:49:39

要生成图,可以将行设置为有向图的路径。一种简单的方法是定义一个 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,然后​​我们就可以gorupby在索引上将其聚合为列表。然后创建一个有向图,并使用以下命令设置路径nx.add_path

G = nx.DiGraph()
for path in paths:
    nx.add_path(G, path)

现在将图形可视化为树状布局,我们可以使用graphviz_layout,它基本上是以下内容的包装器pygraphviz_layout

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)

在此处输入图片说明

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

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

然后按照上面的步骤进行操作,现在你将获得:

在此处输入图片说明

请注意,还有其他一些graphviz布局程序可能与你所想的更加相似。例如circo

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

在此处输入图片说明