【问题标题】:Find all possible connections between child and parent找到孩子和父母之间所有可能的联系
【发布时间】:2021-12-16 21:16:20
【问题描述】:

我正在寻找从所谓的孩子到父母的层次结构中的所有联系。它不完全是子父层次结构,因为通过“intermediate_parents”,一个孩子和一个父母之间可能存在许多联系。并且一个孩子可以与少数父母联系,反之亦然。例如:

Child Parent Class
1 2 C
1 3 C
1 4 B
1 9 A
2 4 B
2 6 D
2 8 S
3 6 C
4 5 A
5 6 D

结果如下:

Child Ultimate_Parent Class Path Connection
1 6 C 1-2-4-5-6 Indirect
1 6 C 1-2-6 Indirect
1 8 C 1-2-8 Indirect
1 6 C 1-3-6 Indirect
1 6 B 1-4-5-6 Indirect
1 9 A 1-9 Direct
2 6 B 2-4-5-6 Indirect
2 6 D 2-6 Direct
2 8 S 2-8 Direct
3 6 C 3-6 Direct
4 6 A 4-5-6 Indirect
5 6 D 5-6 Direct

在df中输入:

df = pd.DataFrame({'Child': ['1', '1', '1', '1', '2', '2', '2', '3', '4', '5'], 
                   'Parent': ['2','3','4','9','4','6','8','6','5','6'],
                   'Class': ['C','C','B','A','B','D','S','C','A','D']})  

我首先尝试使用 DiR 图来解决它,但仍然难以完全理解它是如何工作的。我已经在这里向Finding ultimate parent 寻求帮助,但我提出的问题并不完全正确。那个答案是正确的,但我无法将其推断到这种情况。

【问题讨论】:

  • class 是什么意思?另外,为什么child=1, parent=4 没有出现在结果中,即使它们直接连接在输入中? child=1, parent=3 也一样,可能还有其他情况。
  • 你应该试试networkx
  • @KotaMori 导致 4 和 3 不是最终父母。他们有他们的父母,我对临时联系不感兴趣,而只是端到端。
  • @mozway 是的,我试过了。但是我错过了一些连接... G = nx.from_pandas_edgelist(df, source='Parent', target='Child', create_using=nx.DiGraph) root = [node for node, degree in G.in_degree() if degree == 0]ultimate_parent = [node if node in root else list(G.predecessors(node))[0] for node in df['Parent']] df['Ultimate_Parent'] =ultimate_parent df['Connection' ] = np.where(df['Parent'] == df['Ultimate_Parent'], '直接', '间接')

标签: python pandas hierarchy


【解决方案1】:

您可以从没有父节点的节点展开数据。 下面的代码是一个完全使用 pandas 方法并产生所需输出的示例。 如果速度是个问题,那么在没有 pandas 的情况下您可能能够更有效地实现,因为 pandas 不是这种递归操作的最佳工具。

import pandas as pd

df = pd.DataFrame(
  {'Child': ['1', '1', '1', '1', '2', '2', '2', '3', '4', '5'], 
   'Parent': ['2','3','4','9','4','6','8','6','5','6'],
   'Class': ['C','C','B','A','B','D','S','C','A','D']}) 

out = None
while len(df) > 0:
  no_parent = set(df.Parent) - set(df.Child)
  tmp = df[df.Parent.isin(no_parent)]
  if out is None:
    out = tmp.rename(columns={"Child": "Parent", "Parent": "UltimateParent"})
    out["Path"] = out.Parent + "-" + out.UltimateParent
    out["Connection"] = "Direct"
  else:
    tmp = pd.merge(out, tmp, on="Parent", how="inner")
    tmp.Path = tmp.Child + "-" + tmp.Path
    tmp["Class"] = tmp.Class_y.fillna(tmp.Class_x)
    tmp["Parent"] = tmp.Child.fillna(tmp.Parent)
    tmp = tmp.drop(columns=["Child", "Class_x", "Class_y"])
    tmp["Connection"] = "Indirect"
    out = pd.concat((out, tmp), ignore_index=True)
  df = df[~df.Parent.isin(no_parent)]
out = out.rename(columns={"Parent": "Child"}).sort_values("Path")
out
 Child UltimateParent Class       Path Connection
     1              6     C  1-2-4-5-6   Indirect
     1              6     C      1-2-6   Indirect
     1              8     C      1-2-8   Indirect
     1              6     C      1-3-6   Indirect
     1              6     B    1-4-5-6   Indirect
     1              9     A        1-9     Direct
     2              6     B    2-4-5-6   Indirect
     2              6     D        2-6     Direct
     2              8     S        2-8     Direct
     3              6     C        3-6     Direct
     4              6     A      4-5-6   Indirect
     5              6     D        5-6     Direct

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-20
    • 1970-01-01
    • 2019-01-14
    • 1970-01-01
    • 2018-01-29
    相关资源
    最近更新 更多