【问题标题】:Create a tree structure from a graph从图创建树结构
【发布时间】:2022-02-08 19:59:03
【问题描述】:

我正在尝试找到正确的方法来绘制包含用户通常在不同位置花费的时间量信息的数据集。重要的是,我的数据中有一些类别和子类别的粒度级别越来越高(例如,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,但我不确定它们中的任何一个是否具有我正在寻找的功能。

这是我想要制作的粗略近似值:

【问题讨论】:

    标签: python tree visualization networkx graph-theory


    【解决方案1】:

    要生成图形,您可以将行设置为有向图的路径。一种简单的方法是定义 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 并聚合为列表。然后创建一个directed graph 并使用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)
    

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

    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)
    

    【讨论】:

    • 不错的解决方案,关于为每个级别添加描述的方法有什么想法(“building”、“subcat1”等)?
    【解决方案2】:

    也许ETE 包可以帮助你。 ETE 是一个 python 包,用于编程树渲染和可视化。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-18
      • 1970-01-01
      • 2021-12-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多