Python:从共生矩阵创建无向加权图

时间:2015-09-12 02:44:24

标签: python matrix graph networkx defaultdict

我正在使用Python 2.7创建一个可以使用Twitter数据并对其进行分析的项目。主要概念是收集推文并获取该推文集合中使用的最常见的主题标签,然后我需要创建一个图表,其中主题标签将是节点。如果这些主题标签碰巧出现在同一个推文中,那将是图中的边缘,并且该边缘的权重将是同现数。所以我正在尝试使用defaultdict(lambda : defaultdict(int))创建字典字典,并使用networkx.from_dict_of_dicts

创建图表

我创建共生矩阵的代码是

def coocurrence (common_entities):


com = defaultdict(lambda : defaultdict(int))

# Build co-occurrence matrix
for i in range(len(common_entities)-1):            
    for j in range(i+1, len(common_entities)):
        w1, w2 = sorted([common_entities[i], common_entities[j]])                
        if w1 != w2:
            com[w1][w2] += 1


return com

但为了使用networkx.from_dict_of_dicts,我需要采用以下格式:com= {0: {1:{'weight':1}}}

您有什么想法可以解决这个问题吗?或者以不同的方式创建这样的图形?

2 个答案:

答案 0 :(得分:1)

首先,我会先对实体进行排序,这样你就不会在循环中不断运行排序。然后我会使用itertools.combinations来获得组合。通过这些更改直接翻译您需要的内容是:

from itertools import combinations
from collections import defaultdict


def coocurrence (common_entities):

    com = defaultdict(lambda : defaultdict(lambda: {'weight':0}))

    # Build co-occurrence matrix
    for w1, w2 in combinations(sorted(common_entities), 2):
        if w1 != w2:
            com[w1][w2]['weight'] += 1

    return com

print coocurrence('abcaqwvv')

首先构建其他东西然后在第二个循环中生成最终答案可能更有效(更少索引和创建更少的对象)。第二个循环不会运行与第一个循环一样多的循环,因为已经计算了所有计数。此外,由于第二个循环没有运行多个循环,因此将if statement推迟到第二个循环可能会节省更多时间。像往常一样,如果您愿意,可以在多个变体上运行timeit,但这是两个循环解决方案的一个可能示例:

def coocurrence (common_entities):

    com = defaultdict(int)

    # Build co-occurrence matrix
    for w1, w2 in combinations(sorted(common_entities), 2):
        com[w1, w2] += 1

    result = defaultdict(dict)
    for (w1, w2), count in com.items():
        if w1 != w2:
            result[w1][w2] = {'weight': count}
    return result

print coocurrence('abcaqwvv')

答案 1 :(得分:0)

<块引用>

这是工作代码和最好的

def coocurrence(*inputs):
com = defaultdict(int)

for named_entities in inputs:
    # Build co-occurrence matrix
    for w1, w2 in combinations(sorted(named_entities), 2):
        com[w1, w2] += 1
        com[w2, w1] += 1  #Including both directions

result = defaultdict(dict)
for (w1, w2), count in com.items():
    if w1 != w2:
        result[w1][w2] = {'weight': count}
return result