【问题标题】:How to count number of children for every node in an adjacency tree dataframe in R or Python recursively如何递归地计算R或Python中邻接树数据框中每个节点的子节点数
【发布时间】:2016-11-29 08:52:51
【问题描述】:

我有以下数据框:

network_id agent_id parent_id
1          10       6
1          11       7
1          12       7
1          13       8
1          6        5
1          7        5
1          8        5
2         104       101
2         105       101
2         106       101
2         107       102
2         108       103
2         101       100
2         102       100
2         103       100

我需要计算每个网络中每个代理的子节点数,parent_id 显示每个节点的直接连接的父节点。我正在寻找 R 或 Python 中的解决方案

【问题讨论】:

    标签: python r recursion dataframe tree


    【解决方案1】:

    为了在代码中实现更多通用性,我正在更改我之前的答案以使用递归解决方案。我还包括您的最新评论:

    import pandas as pd
    
    cols = ['network_id', 'agent_id', 'parent_id']
    df = pd.DataFrame([[1, 10, 6],
                        [1, 11, 7],
                        [1, 12, 7],
                        [1, 13, 8],
                        [1, 6,  5],
                        [1, 7,  5],
                        [1, 8,  5],
                        [2, 104,101],
                        [2, 105,101],
                        [2, 106,101],
                        [2, 107,102],
                        [2, 108,103],
                        [2, 101,100],
                        [2, 102,100],
                        [2, 103,100]], columns = cols)
    
    # For each network, I create a list of all nodes,
    # including boths nodes that have children and those who don't
    all_nodes_in_networks = df.groupby('network_id')\
                              .apply(lambda x: set(x[['agent_id', 'parent_id']].values.flatten()))\
                              .to_dict()
    
    def find_children(df, node, network, explored_children = []):
        '''
        find direct children of a cerain node within a network 
        '''
        children = df.query('parent_id==@node and network_id==@network')['agent_id'].values.tolist()    
        # Takes care of the case when we go back to an already visited node    
        new_children = set(children) - set(explored_children)
    
        return new_children
    
    def recursive_find_children(df, node, network, explored_children = []):
        '''
        recursively find all children of a certain node within a network
        '''
    
        new_children = find_children(df, node, network, explored_children)
    
        # Exit Case, when we have arrived to a node with no children or we go back to an already visited node
        if not new_children:
    
            return set(explored_children)
    
        else: 
        # Recursive call
        # Add direct children and all children of children (to any nested level)
            new_explored_children = set(explored_children).union(set(new_children))
            return set(explored_children).union(*[recursive_find_children(df, nd,network, new_explored_children) for nd in new_children])
    

    现在让我们将上面的函数应用到所有节点:

    all_children = {network : {node : recursive_find_children(df, node, network) for node in all_nodes_in_networks[network]} for network in all_nodes_in_networks}
    
    all_children
    Out[113]: 
    {1: {5: {6L, 7L, 8L, 10L, 11L, 12L, 13L},
      6: {10L},
      7: {11L, 12L},
      8: {13L},
      10: set(),
      11: set(),
      12: set(),
      13: set()},
     2: {100: {101L, 102L, 103L, 104L, 105L, 106L, 107L, 108L},
      101: {104L, 105L, 106L},
      102: {107L},
      103: {108L},
      104: set(),
      105: set(),
      106: set(),
      107: set(),
      108: set()}}
    
    
    all_children_number = {network: {node: len(all_children[network][node]) for node in all_children[network]} for network in all_children}
    
    all_children_number
    Out[114]: 
    {1: {5: 7, 6: 1, 7: 2, 8: 1, 10: 0, 11: 0, 12: 0, 13: 0},
     2: {100: 8, 101: 3, 102: 1, 103: 1, 104: 0, 105: 0, 106: 0, 107: 0, 108: 0}}
    

    希望这会有所帮助,并且代码足够清晰。

    【讨论】:

    • 不,我不想计算直接连接的孩子。例如代理 5 有 7 个孩子而不是 3
    • 您能否澄清您的问题并提供所需的输出?我不清楚
    • 如何找到孩子和孩子的孩子。换句话说,特定节点下的所有节点。
    • 我需要计算 5m 以下较低级别的每个代理有 3 个代理直接连接到 5,例如 7 有两个孩子,6 和 8 有 1 个孩子,所以总代理低于 5是 7. 这就是我要找的。否则仅使用 group by 很简单,我正在寻找递归解决方案
    • 相应更新。让我知道这是否是您正在寻找的东西
    猜你喜欢
    • 1970-01-01
    • 2015-08-31
    • 1970-01-01
    • 2018-10-31
    • 1970-01-01
    • 2022-08-15
    • 2020-02-21
    • 1970-01-01
    • 2014-08-12
    相关资源
    最近更新 更多