社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

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

DrWhat • 3 年前 • 1385 次点击  

我们有一个表,它包含一个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
 
1385 次点击  
文章 [ 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

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