GraphScope 在大规模图分析基础上,提供了一套兼容 NetworkX 的图分析接口。 本文中我们将介绍如何用 GraphScope 像 NetworkX 一样进行图分析。
NetworkX 的图分析过程一般首先进行图的构建,示例中我们首先建立一个空图,然后通过 NetworkX 的接口逐步扩充图的数据。
# Install graphscope package if you are NOT in the Playground
!pip3 install graphscope
import networkx
# 初始化一个空的无向图
G = networkx.Graph()
# 通过 add_edges_from 接口添加边列表,此处添加了两条边(1, 2)和(1, 3)
G.add_edges_from([(1, 2), (1, 3)])
# 通过 add_node 添加点4
G.add_node(4)
接着使用 NetworkX 来查询一些图的信息
# 使用 G.number_of_nodes 查询图G目前点的数目
G.number_of_nodes()
# 类似地,G.number_of_edges 可以查询图G中边的数量
G.number_of_edges()
# 通过 G.degree 来查看图G中每个点的度数
sorted(d for n, d in G.degree())
最后通过调用 NetworkX 内置的算法对图G进行分析
# 调用 connected_components 算法分析图G的联通分量
list(networkx.connected_components(G))
# 调用 clustering 算法分析图G的聚类情况
networkx.clustering(G)
图的构建
使用 GraphScope 的 NetworkX 兼容接口,我们只需要简单地将教程中的import netwokx as nx
替换为import graphscope.nx as nx
即可。
GraphScope 支持与 NetworkX 完全相同的载图语法,这里我们使用nx.Graph()
来建立一个空的无向图。
import graphscope.nx as nx
# 我们可以建立一个空的无向图
G = nx.Graph()
增加节点和边
GraphScope 的图操作接口也保持了与 NetworkX 的兼容,用户可以通过add_node
和 add_nodes_from
来添加节点,通过add_edge
和add_edges_from
来添加边。
# 通过 add_node 一次添加一个节点
G.add_node(1)
# 或从任何 iterable 容器中添加节点,如列表
G.add_nodes_from([2, 3])
# 如果容器中是元组的形式,还可以在添加节点的同时,添加节点属性
G.add_nodes_from([(4, {"color": "red"}), (5, {"color": "green"})])
# 对于边,可以通过 add_edge 的一次添加一条边
G.add_edge(1, 2)
e = (2, 3)
G.add_edge(*e)
# 通过 add_edges_from 添加边列表
G.add_edges_from([(1, 2), (1, 3)])
# 或者通过边元组的方式,在添加边的同时,添加边的属性
G.add_edges_from([(1, 2), (2, 3, {'weight': 3.1415})])
查询图的元素
GraphScope 支持兼容 NetworkX 的图查询接口。用户可以通过number_of_nodes
和number_of_edges
来获取图点和边的数量,通过nodes
, edges
,adj
和degree
等接口来获取图当前的点和边,以及点的邻居和度数等信息。
# 查询目前图中点和边的数目
G.number_of_nodes()
G.number_of_edges()
# 列出目前图中的点和边
list(G.nodes)
list(G.edges)
# 查询某个点的邻居
list(G.adj[1])
# 查询某个点的度
G.degree(1)
从图中删除元素
像 NetworkX 一样, GraphScope 也可以使用与添加元素相类似的方式从图中删除点和边,对图进行修改。例如可以通过remove_node
和remove_nodes_from
来删除图中的节点,通过remove_edge
和remove_edges_from
来删除图中的边。
# 通过 remove_node 删除一个点
G.remove_node(5)
list(G.nodes)
G.remove_nodes_from([4, 5])
list(G.nodes)
# 通过 remove_edge 删除一条边
G.remove_edge(1, 2)
list(G.edges)
# 通过 remove_edges_from 删除多条边
G.remove_edges_from([(1, 3), (2, 3)])
list(G.edges)
# 我们再来看一下现在的点和边的数目
G.number_of_nodes()
G.number_of_edges()
图分析
GraphScope 可以通过兼容 NetworkX 的接口来对图进行各种算法的分析,示例里我们构建了一个简单图,然后分别使用connected_components
分析图的联通分量,使用clustering
来得到图中每个点的聚类系数,以及使用all_pairs_shortest_path
来获取节点两两之间的最短路径。
# 首先构建图
G = nx.Graph()
G.add_edges_from([(1, 2), (1, 3)])
G.add_node(4)
# 通过 connected_components 算法找出图中的联通分量
list(nx.connected_components(G))
# 通过 clustering 算法计算每个点的聚类系数
nx.clustering(G)
sp = dict(nx.all_pairs_shortest_path(G))
sp[3]
图的简单绘制
同 NetworkX 一样,GraphScope支持通过draw
将图进行简单地绘制出来,底层依赖的是matplotlib
的绘图功能。
如果系统未安装matplotlib
, 我们首先需要安装一下matplotlib
包
!pip3 install matplotlib
使用 GraphScope 来进行简单地绘制图
# 创建一个5个点的 star graph
G = nx.star_graph(5)
# 使用 nx.draw 绘制图
nx.draw(G, with_labels=True, font_weight='bold')
我们通过一个简单的实验来看一下 GraphScope 对比 NetworkX 在算法性能上到底提升多少。
实验使用来自 snap 的 [twitter] 图数据(https://snap.stanford.edu/data/ego-Twitter.html), 测试算法是 NetworkX 内置的 clustering 算法。
我们首先准备下数据,使用 wget 将数据集下载到本地
!wget https://raw.githubusercontent.com/GraphScope/gstest/master/twitter.e -P /tmp
接着我们分别使用 GraphScope 和 NetworkX 载入 snap-twitter 数据
import os
import graphscope.nx as gs_nx
import networkx as nx
# 使用 NetworkX 载入 snap-twitter 图数据
g1 = nx.read_edgelist(
os.path.expandvars('/tmp/twitter.e'), nodetype=int, data=False, create_using=nx.Graph
)
type(g1)
# 使用 GraphScope 载入相同的 snap-twitter 图数据
g2 = gs_nx.read_edgelist(
os.path.expandvars('/tmp/twitter.e'), nodetype=int, data=False, create_using=gs_nx.Graph
)
type(g2)
最后我们使用 clustering 算法来对图进行聚类分析,来看一下 GraphScope 对比 NetworkX 在算法性能上有多少提升
%%time
# 使用 GraphScope 计算图中每个点的聚类系数
ret_gs = gs_nx.clustering(g2)
%%time
# 使用 NetworkX 计算图中每个点的聚类系数
ret_nx = nx.clustering(g1)
# 对比下两者的结果是否一致
ret_gs == ret_nx