【问题标题】:Create adjacency matrix in python from csv dataset从csv数据集在python中创建邻接矩阵
【发布时间】:2015-06-29 13:04:00
【问题描述】:

我的数据格式如下:

eventid    mnbr
20         1
26         1
12         2
14         2
15         3
14         3
10         3

eventid 是成员参加的活动,数据表示为面板,因此您可以看到每个成员参加多个活动,并且多个成员可以参加同一个活动。我的目标是创建一个邻接矩阵,显示:

 mnbr  1    2    3
 1     1    0    0
 2     0    1    1
 3     0    1    1

只要有两个成员参加同一活动,就会出现 1。我成功地将 csv 文件的列读入 2 个单独的 1D numpy 数组。但是,在这里我不确定如何继续。如何最好地使用第 2 列创建矩阵,然后如何使用第 1 列填充值?我知道我没有发布任何代码并且不期望在这方面有任何解决方案,但非常感谢如何以有效方式解决问题的想法。我有大约 300 万个观察值,因此创建过多的外部变量将是有问题的。提前致谢。我收到通知说我的问题可能重复,但我的问题是解析数据而不是创建邻接矩阵。

【问题讨论】:

  • 您是否估计过您拥有多少独特的会员和活动?如果您的数组被称为eventidmnbr,您可以通过执行len(set(eventid))len(set(mnbr)) 来确定这一点
  • 另外,您需要使用除矩阵之外的其他东西来存储您的结果,因为除非您有几千 Gb 的 RAM,否则 300 万平方整数将不适合内存。可能是稀疏矩阵或邻接表。
  • 对不起,上面的错误,如果你想使用矩阵,你需要检查len(set(mnbr))**2整数是否适合内存。
  • @Gabriel 刚刚检查了长度,我能够为这个任务使用一个子集,我目前有 280801 个观察值。

标签: python csv numpy adjacency-matrix


【解决方案1】:

这里有一个解决方案。它不会直接为您提供请求的邻接矩阵,而是为您提供自己创建它所需的内容。

#assume you stored every line of your input as a tuples (eventid, mnbr).
observations = [(20, 1), (26, 1), (12, 2), (14, 2), (15,3 ), (14, 3), (10, 3)]

#then creates an event link dictionary. i.e something that link every event to all its mnbrs
eventLinks = {}

for (eventid, mnbr) in observations :
    #If this event have never been encoutered then create a new entry in links
    if not eventid in eventLinks.keys():
        eventLinks[eventid] = []

    eventLinks[eventid].append(mnbr)

#collect the mnbrs
mnbrs = set([mnbr for (eventid, mnbr) in observations])

#create a member link dictionary. This one link a mnbr to other mnbr linked to it.
mnbrLinks = { mnbr : set() for mnbr in mnbrs }

for mnbrList in eventLinks.values() :
    #add for each mnbr all the mnbr implied in the same event.
    for mnbr in mnbrList:
        mnbrLinks[mnbr] = mnbrLinks[mnbr].union(set(mnbrList))

print(mnbrLinks)

执行此代码给出以下结果:

{1: {1}, 2: {2, 3}, 3: {2, 3}}

这是一个字典,其中每个mnbr 都有一组关联的邻接mnbrs。这实际上是一个邻接表,即一个压缩的邻接矩阵。您可以扩展它并使用字典键和值作为行和列索引来构建您请求的矩阵。

希望对您有所帮助。 亚瑟。

编辑:我提供了一种使用邻接列表的方法,让您实现自己的邻接矩阵构建。但是你应该考虑真正使用这种数据结构,以防你的数据稀疏。见http://en.wikipedia.org/wiki/Adjacency_list

编辑 2:添加代码将 adjacencyList 转换为一个小智能 adjacencyMatrix

adjacencyList = {1: {1}, 2: {2, 3}, 3: {2, 3}}

class AdjacencyMatrix():

    def __init__(self, adjacencyList, label = ""):
        """ 
        Instanciation method of the class.
        Create an adjacency matrix from an adjacencyList.
        It is supposed that graph vertices are labeled with numbers from 1 to n.
        """

        self.matrix = []
        self.label = label

        #create an empty matrix
        for i in range(len(adjacencyList.keys())):
            self.matrix.append( [0]*(len(adjacencyList.keys())) )

        for key in adjacencyList.keys():
            for value in adjacencyList[key]:
                self[key-1][value-1] = 1

    def __str__(self):
        # return self.__repr__() is another possibility that just print the list of list
        # see python doc about difference between __str__ and __repr__

        #label first line
        string = self.label + "\t"
        for i in range(len(self.matrix)):
            string += str(i+1) + "\t"
        string += "\n"

        #for each matrix line :
        for row in range(len(self.matrix)):
            string += str(row+1) + "\t"
            for column in range(len(self.matrix)):
                string += str(self[row][column]) + "\t"
            string += "\n"


        return string

    def __repr__(self):
        return str(self.matrix)

    def __getitem__(self, index):
        """ Allow to access matrix element using matrix[index][index] syntax """
        return self.matrix.__getitem__(index)

    def __setitem__(self, index, item):
        """ Allow to set matrix element using matrix[index][index] = value syntax """
        return self.matrix.__setitem__(index, item)

    def areAdjacent(self, i, j):
        return self[i-1][j-1] == 1

m = AdjacencyMatrix(adjacencyList, label="mbr")
print(m)
print("m.areAdjacent(1,2) :",m.areAdjacent(1,2))
print("m.areAdjacent(2,3) :",m.areAdjacent(2,3))

此代码给出以下结果:

mbr 1   2   3   
1   1   0   0   
2   0   1   1   
3   0   1   1   

m.areAdjacent(1,2) : False
m.areAdjacent(2,3) : True

【讨论】:

  • 非常感谢您的帮助,有没有直接从这本词典中创建一些常见的邻接可视化?
  • 这是一种常见的邻接可视化;)但是是的。我举个例子。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多