【问题标题】:Creating a nxn Symmetric binary data matrix in python在 python 中创建一个 nxn 对称二进制数据矩阵
【发布时间】:2015-03-19 20:08:51
【问题描述】:

我想在 python 中创建一个 nxn 对称矩阵。假设 n=9,那么我想要如下所示:

array[[0,1,0,0,0,1,1,0,1],[1,0,1,1,1,0,0,0,0],[0,1,0,1,1,0,0,0,0]….]. 

我知道如何做到这一点,首先在 python (np.zeros((9,9)) 中创建一个修女零矩阵,然后使用循环填充它 1 和零。但我觉得这不是 python 的方式. 因此,如果矩阵很大,正在寻找一种使用循环的优化方式会减慢代码。

基本上这是我为无向图创建的邻接矩阵。我的后续问题是如何绘制具有邻接矩阵的图形。任何从邻接矩阵绘制无向图的函数?

请指教。我想学习在 python 中做某​​事而不是使用传统循环的最佳优化/pythonic 方式。

编辑:

我使用以下内容为 30x30 邻接矩阵创建边列表。但是这个边缘列表没有集群中每个节点的对。如果我开始这样做,列表将是巨大的。因此,我下面的图表在集群中的每个节点之间没有边。如何自动化这个边缘列表,这样我就不必手动输入所有边缘对。在图中,我希望集群中的每个节点都与该集群中的其他节点有一条边,并且只有节点 1 和 2 应该在集群边缘与其他集群的节点 16 和 17 之间。

N=30
# Creating a matrix of zeros. 
W=np.zeros((N,N))
# Mentioning the edges to start with. Thinking of a pair of 15 node cluster with two cluster connected by two pair of nodes. 
edge=[[1,2],[1,3],[1,4],[1,5],[1,6],[1,7],[1,8],[1,9],[1,10],[1,11],[1,12],[1,13],[1,14],[1,15],
      [16,17],[16,18],[16,19],[16,20],[16,21],[16,22],[16,23],[16,24],[16,25],[16,26],[16,27],[16,28],[16,29],[16,30],
      [1,16],[2,17]]

# Function for creating adjacency matrix ,populating the zeros matrix with 1 and 0-signifying edges on a node. 
def adjacencyMatrix():
    """This function creates an Adjacency Matrix from a edge set. 
    input-> set of edges to be connected 
    output-> Adjacency matrix (n,n)
    """
    for first,second in edge:
        W[first-1,second-1]=W[second-1][first-1]=1

图表:

【问题讨论】:

  • 您对图表有什么样的访问权限?显然,is_adjacent(source_node, target_node)-type 函数是必需的,但是您是否有一个 get_neighbors(source_node)-type 函数可以返回相邻的 target_nodes 列表?这可以用来加快速度。

标签: python numpy pandas matplotlib


【解决方案1】:

如果您只关心图形和邻接矩阵,您是否必须从矩阵构建图形?还是您乐意反过来做?

你应该看看networkx

牢记评论;你有一组边——你事先知道这些(或者至少你想如何创建它们——你想绘制图形。现在,如果你愿意,你可以单独创建邻接矩阵,类似这样:

A = [[0 for _ in range(N)] for _ in range(N)]
edges = [[1,2], [3,4], [6,1], ..., etc.]
for start, finish in edges: 
  A[start][finish] = A[finish][start] = 1

然后您可以按如下方式进行绘图 - 但是当您从 networkx 获得所有功能时,为什么要这样做呢?您可以通过告诉它您拥有哪些边来创建一个邻接矩阵 - 图和邻接矩阵包含完全相同的信息,只是格式不同,您执行的方式没有区别(可以说是通过添加图的边缘也更具可读性)。

根据您的编辑,您希望拥有两个节点集群,然后让每个集群中的所有节点相互连接,然后再添加一些额外的边。您提到手动执行此操作会很乏味,您是对的:以编程方式执行此操作。

import networkx as nx
from matplotlib import pyplot

G=nx.Graph()

# Why not group your nodes into clusters, since that's how you plan on using them.
node_clusters = [range(10), range(10,20)]


for node_cluster in node_clusters:
  for node in node_cluster:
    for other_node in node_cluster:
      if node != other_node:
        G.add_edge(node, other_node) # we don't actually need to add nodes, as the `add_edge` will add the nodes for us. 

#Add manual edges
G.add_edge(0,10)
G.add_edge(1, 11)


from networkx.linalg.graphmatrix import adjacency_matrix
A = adjacency_matrix(G)
print A

nx.draw(G)

pyplot.show()

老实说,如果每个集群中的每个节点都相互连接,那么实际上并没有大量的点来绘制所有连接,而是将它们汇总起来,因为在更大的节点上可能会绘制出更好的图。

【讨论】:

  • 好吧,我首先要创建一个邻接矩阵。现在我的邻接矩阵基本上是在考虑一些图形的情况下创建的。但我不是从图表开始的。我从一个相邻的矩阵开始。所以第一个问题。是你如何创建一个邻接矩阵(或者基本上用 1 和 0 填充 nxn 矩阵而不使用循环。第二个问题是一旦我有一个邻接矩阵,我如何创建一个显示节点和边的无向图。我想你的答案会有所帮助在第二部分。第一部分有什么想法吗?
  • 这很有帮助。还有一件事。这里不得不提一下边集。什么是节点都喜欢很高。那么就不能只提到每个节点的边集。有没有办法自动化这个?所以假设我想要 30 个节点,每个节点 15 个组成一个集群。所以两个节点集群(每个 15 个)。然后我将在集群中的每对节点之间有一条边,并且集群通过每个集群的两个不同节点对之间的一些 2 条边连接。目前我必须在列表中手动添加这些边缘点。也许自动化上面的边缘列表?
  • 另外我认为边缘需要从 0 开始。否则会引发错误!
  • @Manish 边缘列表中的节点只是一个例子——如果你用 0...N 索引你的节点,那么是的,你需要这样做,如果你是用对象索引它们,然后你可以使用嵌套字典。您可以随心所欲地创建边缘,以编程方式执行它没有问题。
  • 您好,请检查编辑。我正在寻找一种创建邻接矩阵的方法,该矩阵将在集群中的每对节点之间创建边缘,并且我有两个这样的边缘。目前在上图中,每个聚类点仅连接到一个节点。我希望每个节点彼此都有优势。问题是我的边缘列表仅适用于 1 个节点和其他节点。但是,如果我开始为每个节点和其他节点创建一个列表集,那么编写这样的列表将非常痛苦。知道如何自动化吗?
【解决方案2】:

邻接矩阵通常是稀疏的(nnz ~ O(N)),因此它们通常存储在sparse format。最简单的一种是 coo 格式,基本上是三个数组:[row_ids, col_id, value],crs 和 csc 习惯起来有点复杂,但性能更高。使用稀疏表示的核心好处是,当您开始执行时,假设 matvec 通常会获得巨大的加速(假设 nnz ~ O(N) 下的渐近复杂度较低)。

回答您的问题:您可以像这样在pos = [(1, 4), (3, 2)] 的位置构建矩阵:

M = scipy.sparse.coo_matrix(([1]*len(pos), zip(*pos)))

在我看来,这几乎是 Pythonic :)

【讨论】:

  • 你为什么说那是pythonic?我会说它确实不是。
  • @通常会同意。但从我的观点来看,这是非常明确的单行“将它们放在那些位置”(删除了关于形状的部分 - 这实际上是错误的)
  • 我认为我仍然在围栏上,是的,这会有点浪费,但我总是试图在最大可读性方面犯错 - 对我来说,涉及的一件事不是嵌套函数作为对他人的论据。可能只是我,但我更喜欢它。并且特别认为在这里回答问题更有帮助,因为首先提出问题至少包含一些对 python 不完全满意的暗示。
猜你喜欢
  • 2017-03-05
  • 1970-01-01
  • 1970-01-01
  • 2015-09-17
  • 2014-07-15
  • 1970-01-01
  • 2022-01-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多