Py学习  »  Python

有没有办法使用Pandas/Python计算内部表引用菊花链的长度?

DrWhat • 3 年前 • 1388 次点击  

我们有一个表,它包含一个Id,在同一行上,引用了同一个表中的另一个Id。Id记录被引用的Id记录感染。被引用的Id本身可能有也可能没有对另一个Id的引用,它可能不存在,或者它可能成为循环引用(链接回自身)。在熊猫身上,问题看起来有点像这样:

import pandas as pd
import numpy as np
# example data frame
inp = [{'Id': 1, 'refId': np.nan},
   {'Id': 2, 'refId': 1},
   {'Id': 3, 'refId': 2},
   {'Id': 4, 'refId': 3}, 
   {'Id': 5, 'refId': np.nan},
   {'Id': 6, 'refId': 7},
   {'Id': 7, 'refId': 20},
   {'Id': 8, 'refId': 9},
   {'Id': 9, 'refId': 8}, 
   {'Id': 10, 'refId': 8}
   ]
df = pd.DataFrame(inp)
print(df.dtypes)

我想做的是计算表中每一行的引用向后走了多远。逻辑是:

  • 每行以Result=0开始:
  • 如果Ref Id不是nan,则添加1,
  • 如果引用的Id存在,且该引用的Id具有引用,且引用的Id引用不是反向引用,则在结果中添加1,然后 重复此步骤,直到其中一个条件不满足,然后转至 其他的
  • Else(没有引用Id,没有引用Id的引用,或
    引用循环返回上一个引用),返回结果。

示例的结果应该如下所示:

Id  RefId  Result
1     -      0
2     1      1
3     2      2
4     3      3
5     -      0
6     7      2
7     20     1
8     9      1
9     8      1
10    8      2

我尝试过的每种方法最终都需要为引用的每一个引用创建一个新列,但这个表非常庞大,我不确定内部表引用的菊花链最终会有多长。我希望有更好的方法,这对我来说不太难学。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/132341
 
1388 次点击  
文章 [ 1 ]  |  最新文章 3 年前
mozway
Reply   •   1 楼
mozway    3 年前

这是一个图形问题,因此可以使用 networkx .

将数据帧转换为有向图:

import networkx as nx

G = nx.from_pandas_edgelist(df.fillna(-1).astype(int),
                            source='Id', target='refId',   # source -> target
                            create_using=nx.DiGraph()      # directed graph
                            )

# removing the NaN (replaced by "-1" for enabling indexing)
G.remove_node(-1)

下面给出一张图表:

graph

然后简单地数一数孩子们:

nodes = {n: len(nx.descendants(G,n)) for n in G.nodes}

df['Result'] = df['Id'].map(lambda x: nodes.get(x, 0))

输出:

   Id  refId  Result
0   1    NaN       0
1   2    1.0       1
2   3    2.0       2
3   4    3.0       3
4   5    NaN       0
5   6    7.0       2
6   7   20.0       1
7   8    9.0       1
8   9    8.0       1
9  10    8.0       2

注意。结果有点不同,所以也许我没有完全理解你的逻辑,但这给了你大致的想法。请详细说明逻辑。