Networkx - 从检测到的社区生成的子图的熵

4

我有四个函数用于复杂网络分析中的某些统计计算。

import networkx as nx
import numpy as np
import math
from astropy.io import fits 

图的度分布:

def degree_distribution(G):
    vk = dict(G.degree())
    vk = list(vk.values()) # we get only the degree values
    maxk = np.max(vk)
    mink = np.min(min)
    kvalues= np.arange(0,maxk+1) # possible values of k
    Pk = np.zeros(maxk+1) # P(k)
    for k in vk:
        Pk[k] = Pk[k] + 1
    Pk = Pk/sum(Pk) # the sum of the elements of P(k) must to be equal to one
    
    return kvalues,Pk

图的社区检测:

def calculate_community_modularity(graph):
    
    communities = greedy_modularity_communities(graph) # algorithm
    modularity_dict = {} # Create a blank dictionary

    for i,c in enumerate(communities): # Loop through the list of communities, keeping track of the number for the community
        for name in c: # Loop through each neuron in a community
            modularity_dict[name] = i # Create an entry in the dictionary for the neuron, where the value is which group they belong to.

    nx.set_node_attributes(graph, modularity_dict, 'modularity')
    
    print (graph_name)
    for i,c in enumerate(communities): # Loop through the list of communities
        #if len(c) > 2: # Filter out modularity classes with 2 or fewer nodes
            print('Class '+str(i)+':', len(c)) # Print out the classes and their member numbers
    return modularity_dict
            

图的模块化得分:

def modularity_score(graph):
    return nx_comm.modularity(graph, nx_comm.label_propagation_communities(graph))

最后需要展示的是熵图:

def shannon_entropy(G):
    k,Pk = degree_distribution(G)
    H = 0
    for p in Pk:
        if(p > 0):
            H = H - p*math.log(p, 2)
    return H

问题

我现在想要做的是为每个社区(转化为子图)找到本地熵,并保留边缘信息。

这可行吗?怎么做?

编辑

所使用的矩阵可以在此链接中找到:

数据集

with fits.open('mind_dataset/matrix_CEREBELLUM_large.fits') as data:
    matrix = pd.DataFrame(data[0].data.byteswap().newbyteorder())

然后将邻接矩阵转换成图形,命名为'graph'或者'G':

def matrix_to_graph(matrix):
    from_matrix = matrix.copy()
    to_numpy = from_matrix.to_numpy()
    G = nx.from_numpy_matrix(to_numpy)
    return G 

编辑2

根据下面提供的答案,我创建了另一个函数:

def community_entropy(modularity_dict):
    communities = {}

    #create communities as lists of nodes
    for node, community in modularity_dict.items():
        if community not in communities.keys():
            communities[community] = [node]
        else:
            communities[community].append(node)

    print(communities)
    #transform lists of nodes to actual subgraphs
    for subgraph, community in communities.items():
        communities[community] = nx.Graph.subgraph(subgraph)
        
    local_entropy = {}
    for subgraph, community in communities.items():
        local_entropy[community] = shannon_entropy(subgraph)
        
    return local_entropy

并且:

cerebellum_graph = matrix_to_graph(matrix)
modularity_dict_cereb = calculate_community_modularity(cerebellum_graph)
community_entropy_cereb = community_entropy(modularity_dict_cereb)

但是它会抛出以下错误:
TypeError: subgraph()缺少1个必需的位置参数:'nodes'

2
看起来,在 calculate_community_modularity 中,您使用 greedy_modularity_communities 创建一个字典 modularity_dict,将图中的节点映射到一个社区。为什么不能将 modularity_dict 中的每个子图社区传递到 shannon_entropy 中,以计算该社区的熵? - Warlax56
1
如果你想回答,我会很高兴接受它。 - 8-Bit Borges
您能定义每个函数的输入吗?例如,Ggraph 分别代表什么? - Warlax56
2个回答

2
使用我在你的问题这里提供的代码来从社区创建图形。您可以先为每个社区创建不同的图形(基于图形的community边属性)。然后,您可以使用您的shannon_entropydegree_distribution函数计算每个社区的熵。
请参见下面的代码,该代码基于您在上述其他问题中提供的空手道俱乐部示例:
import networkx as nx
import networkx.algorithms.community as nx_comm
import matplotlib.pyplot as plt
import numpy as np
import math

def degree_distribution(G):
    vk = dict(G.degree())
    vk = list(vk.values()) # we get only the degree values
    maxk = np.max(vk)
    mink = np.min(min)
    kvalues= np.arange(0,maxk+1) # possible values of k
    Pk = np.zeros(maxk+1) # P(k)
    for k in vk:
        Pk[k] = Pk[k] + 1
    Pk = Pk/sum(Pk) # the sum of the elements of P(k) must to be equal to one
    
    return kvalues,Pk

def shannon_entropy(G):
    k,Pk = degree_distribution(G)
    H = 0
    for p in Pk:
        if(p > 0):
            H = H - p*math.log(p, 2)
    return H


G = nx.karate_club_graph()

# Find the communities
communities = sorted(nx_comm.greedy_modularity_communities(G), key=len, reverse=True)

# Count the communities
print(f"The club has {len(communities)} communities.")

'''Add community to node attributes'''
for c, v_c in enumerate(communities):
    for v in v_c:
        # Add 1 to save 0 for external edges
        G.nodes[v]['community'] = c + 1

'''Find internal edges and add their community to their attributes'''
for v, w, in G.edges:
    if G.nodes[v]['community'] == G.nodes[w]['community']:
        # Internal edge, mark with community
        G.edges[v, w]['community'] = G.nodes[v]['community']
    else:
        # External edge, mark as 0
        G.edges[v, w]['community'] = 0


N_coms=len(communities)
edges_coms=[]#edge list for each community
coms_G=[nx.Graph() for _ in range(N_coms)] #community graphs
colors=['tab:blue','tab:orange','tab:green']
fig=plt.figure(figsize=(12,5))

for i in range(N_coms):
  edges_coms.append([(u,v,d) for u,v,d in G.edges(data=True) if d['community'] == i+1])#identify edges of interest using the edge attribute
  coms_G[i].add_edges_from(edges_coms[i]) #add edges

ent_coms=[shannon_entropy(coms_G[i]) for i in range(N_coms)] #Compute entropy
for i in range(N_coms):
  plt.subplot(1,3,i+1)#plot communities
  plt.title('Community '+str(i+1)+ ', entropy: '+str(np.round(ent_coms[i],1)))
  pos=nx.circular_layout(coms_G[i])
  nx.draw(coms_G[i],pos=pos,with_labels=True,node_color=colors[i])  

运行结果如下:

在此输入图片描述


0

calculate_community_modularity中,你使用greedy_modularity_communities创建一个字典modularity_dict,将图中的节点映射到一个community。如果我理解正确,你可以将modularity_dict中的每个子图社区传递到shannon_entropy中,以计算该社区的熵。


伪代码

这是伪代码,所以可能会有一些错误。不过这应该能传达原则。

运行calculate_community_modularity后,您将得到一个字典,其中键是每个节点,值是其所属的社区。

modularity_dict = {node_1: community_1, node_2: community_1, node_3: community_2}

我从未使用过nx,但看起来你可以根据节点列表提取子图。因此,您将遍历字典,并为每个社区创建一个节点列表。然后,您将使用该节点列表从nx中提取该社区的实际子图。

communities = {}

#create communities as lists of nodes
for node, community in modularity_dict.iteritems():
    if community not in communities.keys():
        communities[community] = [node]
    else:
        communities[community].append(node)

#transform lists of nodes to actual subgraphs
for subgraph, community in communities.iteritems():
    communities[community] = networkx.Graph.subgraph(subgraph)


现在,communities 是一个字典,其键为社区ID,值为定义该社区的nx子图,因此您应该能够通过shannon_entropy运行这些子图,因为子图的类型与原始图的类型相同。
local_entropy = {}
for subgraph, community in communities.iteritems():
    local_entropy[community] = shannon_entropy(subgraph)

谢谢,但我想要一个带有代码的答案... - 8-Bit Borges
哦,我明白了。我会添加一些伪代码来描述我的想法。 - Warlax56
为了获得真正的矩阵,您需要导入 from astropy.io import fits。但是如果您喜欢,也可以使用伪代码。 - 8-Bit Borges
谢谢,但是不知何故这个方法不起作用,抛出了错误:TypeError: subgraph() missing 1 required positional argument: 'nodes'。此外,我认为图对象还需要关于边的信息:Graph with 1858 nodes and 8570 edges,而这似乎在社区中缺失了。 - 8-Bit Borges
也许最好不要使用伪代码,而是使用链接中的真实矩阵,因为我有这个矩阵,并且有将其转换为图形等的手段... - 8-Bit Borges
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接