图分析
igraph 使得从简单的操作(如添加和删除节点)到复杂的理论构建(如社区检测)的图/网络分析成为可能。阅读 API 参考 以了解每个函数和类的详细信息。
以下示例的上下文将是导入igraph(通常作为ig),拥有Graph类,并拥有一个或多个可用的图:
>>> import igraph as ig
>>> from igraph import Graph
>>> g = Graph(edges=[[0, 1], [2, 3]])
要获取图的摘要表示,请使用 Graph.summary()。例如:
>>> g.summary(verbosity=1)
将提供相当详细的描述。
要复制一个图,请使用Graph.copy()。这是一个“浅”复制:属性中的任何可变对象都不会被复制(它们将引用相同的实例)。
如果你想复制一个图包括其所有属性,请使用Python的deepcopy模块。
顶点和边
顶点编号从0到n-1,其中n是图中顶点的数量。这些被称为“顶点ID”。
要计算顶点数量,请使用Graph.vcount():
>>> n = g.vcount()
边的编号也从0到m-1,并且可以通过Graph.ecount()进行计数:
>>> m = g.ecount()
要获取一系列顶点,请使用它们的ID和Graph.vs:
>>> for v in g.vs:
>>> print(v)
同样地,对于边,使用 Graph.es:
>>> for e in g.es:
>>> print(e)
你可以像索引和切片列表一样索引和切片顶点和边:
>>> g.vs[:4]
>>> g.vs[0, 2, 4]
>>> g.es[3]
注意
vs 和 es 属性是具有自己有用方法的特殊序列。有关完整列表,请参阅 API reference。
如果你更喜欢普通的边列表,你可以使用Graph.get_edge_list()。
发病率
要获取边的两个端点,请使用 Edge.source 和 Edge.target:
>>> e = g.es[0]
>>> v1, v2 = e.source, e.target
反之,要从源顶点和目标顶点获取边,你可以使用Graph.get_eid(),或者对于多对源/目标顶点,使用Graph.get_eids()。询问两个顶点是否直接连接的布尔版本是Graph.are_adjacent()。
要获取与顶点相关的边,你可以使用 Vertex.incident(), Vertex.out_edges() 和
Vertex.in_edges()。这三者在无向图中是等价的,但在有向图中则不同:
>>> v = g.vs[0]
>>> edges = v.incident()
Graph.incident() 函数实现了相同的功能,但基于顶点ID的语法略有不同:
>>> edges = g.incident(0)
要获取图的完整邻接/关联列表表示,请使用 Graph.get_adjlist()、Graph.g.get_inclist() 或者,对于二分图,使用 Graph.get_biadjacency()。
邻里
要计算邻居、后继和前驱,可以使用方法 Graph.neighbors()、Graph.successors() 和
Graph.predecessors()。在无向图中,这三个方法给出的答案相同,并且具有类似的双重语法:
>>> neis = g.vs[0].neighbors()
>>> neis = g.neighbors(0)
要获取与一个或多个初始顶点在一定距离内的顶点列表,你可以使用 Graph.neighborhood():
>>> g.neighborhood([0, 1], order=2)
要找到邻域大小,可以使用 Graph.neighborhood_size()。
学位
要计算节点的度、入度或出度,请使用 Vertex.degree()、Vertex.indegree() 和 Vertex.outdegree():
>>> deg = g.vs[0].degree()
>>> deg = g.degree(0)
要计算顶点列表中的最大度数,请使用Graph.maxdegree()。
Graph.knn() 计算邻居的平均度数。
添加和删除顶点和边
要向图中添加节点,请使用 Graph.add_vertex() 和 Graph.add_vertices():
>>> g.add_vertex()
>>> g.add_vertices(5)
这会就地更改图 g。如果您愿意,可以指定顶点的名称。
要删除节点,请使用 Graph.delete_vertices():
>>> g.delete_vertices([1, 2])
再次,你可以指定名称或实际的Vertex对象来代替。
要添加边,请使用 Graph.add_edge() 和 Graph.add_edges():
>>> g.add_edge(0, 2)
>>> g.add_edges([(0, 2), (1, 3)])
要删除边,请使用 Graph.delete_edges():
>>> g.delete_edges([0, 5]) # remove by edge id
你也可以移除源节点和目标节点之间的边。
要收缩顶点,请使用Graph.contract_vertices()。收缩顶点之间的边将变成循环。
图形操作符
可以计算图之间的并集、交集、差集和其他集合操作(运算符)。
计算图的并集(保留任一图中的节点/边):
>>> gu = ig.union([g, g2, g3])
同样适用于交集(保留所有节点/边):
>>> gu = ig.intersection([g, g2, g3])
这两个操作保留属性,并且可以通过一些变化来执行。最重要的是,顶点可以通过id(数字)或名称在图之间进行匹配。
这些以及其他操作也可作为 Graph 类的方法使用:
>>> g.union(g2)
>>> g.intersection(g2)
>>> g.disjoint_union(g2)
>>> g.difference(g2)
>>> g.complementer() # complement graph, same nodes but missing edges
甚至作为数值运算符:
>>> g |= g2
>>> g_intersection = g and g2
拓扑排序
要对图进行拓扑排序,请使用 Graph.topological_sorting():
>>> g = ig.Graph.Tree(10, 2, mode=ig.TREE_OUT)
>>> g.topological_sorting()
图遍历
一个常见的操作是遍历图。igraph 目前通过 Graph.bfs() 和 Graph.bfsiter() 提供了广度优先搜索(BFS):
>>> [vertices, layers, parents] = g.bfs()
>>> it = g.bfsiter() # Lazy version
深度优先搜索通过Graph.dfs()和Graph.dfsiter()具有类似的基础设施:
>>> [vertices, parents] = g.dfs()
>>> it = g.dfsiter() # Lazy version
要从某个顶点执行随机游走,请使用 Graph.random_walk():
>>> vids = g.random_walk(0, 3)
路径查找和切割
提供了几种路径查找算法:
Graph.shortest_paths()或Graph.get_shortest_paths()Graph.get_all_shortest_paths()Graph.spanning_tree()找到一个最小生成树
以及与切割和路径相关的函数:
Graph.mincut()计算源顶点和目标顶点之间的最小割Graph.st_mincut()- 与前一个相同,但返回一个更简单的数据结构Graph.mincut_value()- 与上一个相同,但只返回值Graph.edge_connectivity()或Graph.edge_disjoint_paths()或Graph.adhesion()Graph.vertex_connectivity()或Graph.cohesion()
另请参阅流程部分。
全局属性
有许多全局图度量可用。
基础:
Graph.diameter()或Graph.get_diameter()Graph.girth()Graph.radius()Graph.average_path_length()
分布:
连接性:
Graph.all_minimal_st_separators()Graph.minimum_size_separators()Graph.cut_vertices()或Graph.articulation_points()
派系和主题:
Graph.clique_number()(也称为Graph.omega())Graph.cliques()Graph.maximal_cliques()Graph.largest_cliques()Graph.motifs_randesu()和Graph.motifs_randesu_estimate()Graph.motifs_randesu_no()计算模体的数量
有向无环图:
Graph.is_dag()Graph.feedback_arc_set()Graph.topological_sorting()
最优性:
Graph.farthest_points()Graph.maximal_cliques()Graph.largest_cliques()Graph.independence_number()(也称为Graph.alpha())Graph.maximal_independent_vertex_sets()Graph.largest_independent_vertex_sets()Graph.mincut_value()Graph.feedback_arc_set()
其他复杂的措施包括:
Graph.assortativity()Graph.assortativity_degree()Graph.assortativity_nominal()Graph.density()Graph.transitivity_undirected()Graph.reciprocity()(有向图)Graph.isoclass()(仅限3或4个顶点)
布尔属性:
Graph.is_bipartite()Graph.is_connected()Graph.is_dag()Graph.is_directed()Graph.is_simple()Graph.has_multiple()
顶点属性
可以计算一系列顶点级别的属性。相似性度量包括:
Graph.similarity_dice()Graph.similarity_jaccard()Graph.similarity_inverse_log_weighted()Graph.diversity()
结构性的:
Graph.authority_score()Graph.hub_score()Graph.betweenness()Graph.bibcoupling()Graph.closeness()Graph.constraint()Graph.cocitation()Graph.coreness()(也称为Graph.shell_index())Graph.eccentricity()Graph.eigenvector_centrality()Graph.harmonic_centrality()Graph.personalized_pagerank()Graph.strength()Graph.transitivity_local_undirected()
连接性:
Graph.subcomponent()Graph.is_separator()Graph.is_minimal_separator()
边属性
至于顶点,边属性也被实现。基本属性包括:
Graph.is_loop()Graph.is_multiple()Graph.is_mutual()Graph.count_multiple()
以及更复杂的:
Graph.edge_betweenness()
矩阵表示
矩阵相关的功能包括:
Graph.get_adjacency_sparse()(稀疏 CSR 矩阵版本)Graph.laplacian()
聚类
igraph 包含了几种用于无监督图聚类和社区检测的方法:
Graph.components()(也称为Graph.connected_components()): 连通组件Graph.community_multilevel()(Louvain的一个版本)Graph.community_optimal_modularity()(精确解,小于100个顶点)
简化、排列和重新布线
要检查一个图是否是简单的,你可以使用 Graph.is_simple():
>>> g.is_simple()
要简化图形(去除多重边和环),请使用 Graph.simplify():
>>> g_simple = g.simplify()
要返回图的有向/无向副本,请分别使用 Graph.as_directed() 和 Graph.as_undirected()。
要置换顶点的顺序,你可以使用 Graph.permute_vertices():
>>> g = ig.Tree(6, 2)
>>> g_perm = g.permute_vertices([1, 0, 2, 3, 4, 5])
规范排列可以通过Graph.canonical_permutation()获得,然后可以直接传递给上述函数。
要随机重新连接图,有以下步骤:
Graph.rewire()- 保持度分布Graph.rewire_edges()- 每个端点的固定重连概率
折线图
要计算图g的线图,它表示g的边的连接性,你可以使用Graph.linegraph():
>>> g = Graph(n=4, edges=[[0, 1], [0, 2]])
>>> gl = g.linegraph()
在这种情况下,折线图有两个顶点,代表原始图的两条边,以及一条边,代表这两条原始边接触的点。
组合和子图
函数 Graph.decompose() 将图分解为子图。相反,函数 Graph.compose() 返回两个图的组合。
要计算由某些顶点/边跨越的子图,请使用 Graph.subgraph()(也称为 Graph.induced_subgraph())和 Graph.subgraph_edges():
>>> g_sub = g.subgraph([0, 1])
>>> g_sub = g.subgraph_edges([0])
要计算最小生成树,请使用 Graph.spanning_tree()。
要计算图的k-核,可以使用方法 Graph.k_core()。
可以从给定节点获取支配树,使用 Graph.dominator()。
二分图可以使用Graph.bipartite_projection()进行分解。投影的大小可以使用Graph.bipartite_projection_size()计算。
态射
igraph 允许在图形之间进行比较:
Graph.isomorphic()Graph.isomorphic_vf2()Graph.subisomorphic_vf2()Graph.subisomorphic_lad()Graph.get_isomorphisms_vf2()Graph.get_subisomorphisms_vf2()Graph.get_subisomorphisms_lad()Graph.count_isomorphisms_vf2()Graph.count_subisomorphisms_vf2()
流程
流是有向图的一个特性。以下是可用的函数:
Graph.maxflow()两个节点之间Graph.maxflow_value()- 类似于前一个,但只返回值
流和割密切相关,因此你可能会发现以下函数也很有用:
Graph.mincut()计算源顶点和目标顶点之间的最小割Graph.st_mincut()- 与前一个相同,但返回一个更简单的数据结构Graph.mincut_value()- 与上一个相同,但只返回值Graph.edge_connectivity()或Graph.edge_disjoint_paths()或Graph.adhesion()Graph.vertex_connectivity()或Graph.cohesion()