在网络图中获取直接边连接

Getting direct edge connections in a network graph

我有下面的网络图:

import networkx as nx
net = nx.Graph()
node_list = ["Gur","Qing","Samantha","Jorge","Lakshmi","Jack","John","Jill"]
edge_list = [("Gur","Qing",{"relation":"work"}),
         ("Gur","Jorge", {"relation":"family"}),
        ("Samantha","Qing", {"relation":"family"}),
        ("Jack","Qing", {"relation":"work"}),
        ("Jorge","Lakshmi", {"relation":"work"}),
        ("Jorge","Samantha",{"relation":"family"}),
        ("Samantha","John", {"relation":"family"}),
        ("Lakshmi","Jack", {"relation":"family"}),
        ("Jack","Jill", {"relation":"charity"}),
        ("Jill","John",{"relation":"family"})]

net.add_nodes_from(node_list)
net.add_edges_from(edge_list)

我想构建一个给定网络、节点名称和关系类型的函数,return是与给定人员直接相关的人员列表。

这是我目前得到的函数:

def get_relations(graph,node,relationship):
        if relationship == 'charity':
            charity = [ (v) for (u,v,d) in net.edges( data = True) if d["relation"]=="charity"]
            return list(set(charity))
        else:

            if relationship == 'work':
                work = [ (v) for (u,v,d) in net.edges( data = True) if d["relation"]=="work"]
                return list(set(work))
            else:

                if relationship == 'family':
                    family = [(v) for (u,v,d) in net.edges( data = True) if d["relation"]=="family"]
                    return list(set(family))
                else:
                    return None

像这样调用函数:

get_connections(net, 'John', 'family')

产生这个输出:

['Gur', 'Samantha', 'John', 'Lakshmi']

虽然这不是我所需要的,但我希望 return 仅那些与 John 有直接联系的人,或者无论节点是什么,具有直接路径,而不是间接路径。

以相同的方式调用该函数应该会产生正确的输出:

['John', 'Jill', 'Samantha', 'Qing', 'Jorge', 'Gur']

代码尝试:

def get_relations(graph,node,relationship):
    if relationship not in {'charity', 'work', 'family'}: 
        return None
    relation_net = nx.Graph([(u,v,d) for (u, v, d) in net.edges( data = True)
                             if d["relation"] == relationship])

    relation_subnet = nx.Graph([(node,v,d) for (u, v, d) in relation_net.edges( data = True)
                             if d["relation"] == relationship])

    return list(set(relation_subnet.nodes))

然而,这仍然是 return 错误的结果。

首先,重构您的函数定义,以便更容易理解:

def get_relations(graph,node,relationship):
    if relationship not in {'charity', 'work', 'family'}:
        return None
    connections = [v for (u, v, d) in G.edges(data = True) if d["relation"] == relationship]
    return list(set(connections))

然后使用较小的网络对其进行测试(也是为了让事情更容易理解):

node_list = ["Gur","Qing","Samantha","Jorge","Lakshmi","Jack","John","Jill"]
edge_list = [
    ("Jack","Qing", {"relation":"work"}),
    ("Gur","Jorge", {"relation":"family"}),
    ("Samantha","Qing", {"relation":"family"}),
    ("Jorge","Samantha",{"relation":"family"}),
    ("Lakshmi","Jack", {"relation":"family"}),
    ("Jill","John",{"relation":"family"})
]
net = nx.Graph()
net.add_nodes_from(node_list)
net.add_edges_from(edge_list)

我们可以立即看到您的函数没有执行您要查找的操作:

调用 get_relations(G, 'John', 'family') 会产生以下输出:

['Jack', 'Jorge', 'Jill', 'Samantha']

您没有在代码中的任何位置使用所需节点的逻辑。

你真正应该做的是:

  1. 找到 net 的子图,该子图由具有正确 'relation' 属性的边和这些边连接到的所有节点组成(称之为 relation_net
  2. 正在寻找包含所需节点的 relation_net(可能是整个事物)的完全连接的组件子图(称之为 relation_sub_net)。
  3. 输出relation_sub_net的节点列表。这是您想要的输出。

如果您想尝试这样做,我相信如果您遇到困难,任何人(包括我自己)都会很乐意为您提供帮助。

根据 PMende 的指导,您的编码尝试非常 接近。问题出在您的第二次提取中,当您尝试仅提取与 John 相连的那些边时:

relation_subnet = nx.Graph([(node,v,d) for (u, v, d) in relation_net.edges( data = True)
                             if d["relation"] == relationship])

(u,v,d)的选择(node,v,d)错误,条件错误。在第一个子句中

(node,v,d) for (u, v, d) in ...

对于 relation_net 中的每个节点,您获取 src、dst 和 arc 值...但随后丢弃 src 并强制 John 进入该位置。这仅在 John 已经恰好是来源时才有效;否则,您刚刚创建了一个新的子网边缘,例如

("John","Jack", {"relation":"family"})  # Lakshmi removed

相反,您需要保留那些包含 John 的边缘 任一 位置。

其次,您的 "relation" 过滤器第二次什么都不做;你已经第一次包括了每一个家庭关系。相反,您需要收集出现在家庭边缘的所有与 John 在一起的人。

relation_subnet = nx.Graph([(u,v,d) for (u, v, d) in relation_net.edges( data = True)
                             if u == node or v == node])

这正确地产生了

['Samantha', 'Jill', 'John']

萨曼莎和吉尔是约翰唯一的直系 link 家庭。如果你想要这个列表上的串联闭包,那么你需要迭代这个过程,将每个新的 family 添加到 Jill and/or Samantha,重复直到没有添加新节点。

你能从那里拿走吗?

大家好 :) 我要感谢大家的时间和帮助,你们确实帮助我提高了我对我所面临的问题的认识和理解,现在我对网络有了更多的了解。我终于得到了我正在寻找的解决方案。事情是这样的:

def get_relations(graph,node,relationship):
    if relationship not in {'charity', 'work', 'family'}:
        return None

    relation_net = nx.Graph([(u,v,d) for (u,v,d) in net.edges(nbunch = net.nodes(), data = True) if u == node or v == node])
    relation_subnet = nx.Graph([(u,v,d) for (u,v,d) in net.edges(nbunch = relation_net.nodes(), data = True) if d['relation']== relationship])
    relation1 = nx.Graph([(u,v,d) for (u,v,d) in net.edges(nbunch = relation_subnet.nodes(), data = True) if d['relation'] == relationship])
    relation2 = nx.Graph([(u,v,d) for (u,v,d) in net.edges(nbunch = relation1.nodes(), data = True) if d['relation'] == relationship])


    return list(set(relation2))

我发布这个是因为也许我认为它有时可以帮助某人。没有你们的帮助,我做不到。再次感谢 :D