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

时间:2018-08-10 20:41:43

标签: python python-3.x graph networkx network-analysis

我有以下网络图:

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)

我想构建一个给定网络,节点名称和关系类型的函数,该函数返回给定人员直接连接的人员列表。

这是我到目前为止获得的功能:

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']

这不是我所需要的,我希望它仅返回那些直接连接到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))

但是,这仍然返回错误的结果。

3 个答案:

答案 0 :(得分:3)

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

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_sub_net(可能是整个事物)的完全连接的组件子图(称为relation_net)。
  3. 输出relation_sub_net的节点列表。这是您想要的输出。

如果您想尝试一下,我敢肯定,如果您遇到困难,很多人(包括我自己)都会很乐意为您提供帮助。

答案 1 :(得分:2)

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

state

(u,v,d)的选择(node,v,d)错误,并且条件错误。在第一句

Child

对于PMende中的每个节点,请获取src,dst和arc值...,然后丢弃src并将relation_subnet = nx.Graph([(node,v,d) for (u, v, d) in relation_net.edges( data = True) if d["relation"] == relationship]) 强制插入该位置。仅当(node,v,d) for (u, v, d) in ... 已经恰好是源时才有效;否则,您只是创建了一个新的子网边缘,例如

relation_net

相反,您需要将包括约翰在内的那些边缘保持在 位置。

第二,您的“关系”过滤器第二次不执行任何操作;您已经第一次包括了所有家庭关系。取而代之的是,您需要收集与约翰一起出现在家庭边缘的每个人。

John

这可以正确产生

John

Samantha和Jill是John的唯一直接联系家庭。如果要在此列表上进行串联关闭,则需要迭代该过程,将("John","Jack", {"relation":"family"}) # Lakshmi removed 的每个新用户添加到Jill和/或Samantha中,重复进行直到没有新节点添加。

你能从那里拿走吗?

答案 2 :(得分:2)

再次向大家问好:)我要感谢大家的宝贵时间和帮助,您的确帮助我提高了对所面临问题的了解和了解,现在我对网络有了更多的了解。我终于找到了我想要的解决方案。就是这样:

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