用 GraphScope 像 NetworkX 一样做图分析

NetworkX 是 Python 上最常用的图分析包,GraphScope 兼容 NetworkX 接口。本文中我们将分享如何用 GraphScope 像 NetworkX 一样在(大)图上进行分析。

背景

NetworkX 是一个用 Python 语言开发的图论与复杂网络建模工具,它内置了常用的图与复杂网络分析算法,提供了一套简单易用的图分析接口,可以方便地进行复杂网络数据分析、仿真建模等工作。NetworkX 的接口设计十分简洁,对于作为刚进入图算法领域的小白来说,NetworkX 的接口可以帮助使用者快速建立起对图数据的感知,并且对于中小型数据集,NetworkX 的接口也是非常好上手的。

但由于 NetworkX 是基于 Python 语言开发,算法的性能并不是它的强项,而且也无法有效地处理工业级别的大规模图数据。基于这一背景,GraphScope 提供了一套兼容 NetworkX 的图分析接口,在能使用像 NetworkX 这样简单易用的接口的同时,也能提供高性能的图分析算法以支持超大规模图数据的处理。

NetworkX 是如何进行图分析的

我们通过一个小例子来简单介绍一下 NetworkX 的图分析过程。

# NetworkX 的图分析过程从图的构建开始
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)

# 接着查看一些图的信息
# 使用 G.number_of_nodes 查询图G目前点的数目
G.number_of_nodes()
# 4

# 类似地,G.number_of_edges 可以查询图G中
# 边的数量
G.number_of_edges()
# 2

# 通过 G.degree 来查看图G中每个点的度数
sorted(d for n, d in G.degree())
# [0, 1, 1, 2]

# 最后调用 NetworkX 内置的算法对对图进行分析
# 调用 connected_components 算法分析图G的
# 联通分量
list(networkx.connected_components(G))
# [{1, 2, 3}, {4},]

# 调用 clustering 算法分析图G的聚类情况
networkx.clustering(G)
# {1: 0, 2: 0, 3: 0, 4: 0}

上述例子只是对 NetworkX 做图分析的一个简单的介绍,更多 NetworkX 的接口介绍以及详细的使用说明,内置的算法等可以参考 NetworkX 官方文档

用 GraphScope 像 NetworkX 一样做图分析

NetworkX 官方的 NetworkX tutorial是一个 NetworkX 接口使用以及图的入门教程。为了演示 GraphScope 对 NetworkX 的兼容性以及如何使用 GraphScope 的 NetworkX 接口进行图分析,下面我们使用 GraphScope 来执行教程中的例子。

使用 GraphScope 的 NetworkX 兼容接口,我们只需要简单地将教程中的import netwokx as nx替换为import graphscope.nx as nx即可, 当然这里只是依照 NetworkX 的惯例使用nx作为别名, 你也可以其他自定义的别名,例如 import graphscope.nx as gs_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()
# 5
G.number_of_edges()
# 3

# 列出目前图中的点和边
list(G.nodes)
# [1, 2, 3, 4, 5]
list(G.edges)
# [(1, 2), (1, 3), (2, 3)]

# 查询某个点的邻居
list(G.adj[1])
# [2, 3]

# 查询某个点的度
G.degree(1)
# 2

从图中删除元素

像 NetworkX 一样, GraphScope 也可以使用与添加元素相类似的方式从图中删除点和边,对图进行修改。例如可以通过remove_node和remove_nodes_from来删除图中的节点,通过remove_edge和remove_edges_from来删除图中的边。

# 通过 remove_node 删除一个点
G.remove_node(5)

# 查看图 G 现有的点,发现点5已经被删除了
list(G.nodes)
# [1, 2, 3, 4]

# 通过 remove_nodes_from 删除多个点
G.remove_nodes_from([4, 5])

# 再查看图 G 现有的点,点4也已经被删除了
list(G.nodes)
# [1, 2, 3]

# 通过 remove_edge 删除一条边
G.remove_edge(1, 2)

# 查看图 G 现有的边,(1, 2) 这条边在G中
# 已经被删除
list(G.edges)
# [(1, 3), (2, 3)]

# 通过 remove_edges_from 删除多条边
G.remove_edges_from([(1, 3), (2, 3)])

# 查看图 G 现有的边,(1, 3), (2, 3) 这两条边
# 在 G 中已经不存在了
list(G.edges)
# []

# 我们再来看一下现在的点和边的数目
G.number_of_nodes()
# 3

G.number_of_edges()
# 0

图分析

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))
# [{4}, {1, 2, 3},]

# 通过 clustering 算法计算每个点的聚类系数
nx.clustering(G)
# {4: 0.0, 1: 0.0, 2: 0.0, 3: 0.0}

# 计算图中节点两两之间的最短路径
sp = dict(nx.all_pairs_shortest_path(G))

# 查看节点3与其他节点的最短路径
sp[3]
# {3: [3], 1: [3, 1], 2: [3, 1, 2]}

图的简单绘制

同 NetworkX 一样,GraphScope 支持通过draw将图进行简单地绘制出来,底层依赖的是matplotlib的绘图功能。

如果系统未安装matplotlib, 我们首先需要安装一下matplotlib包:

pip3 install matplotlib

使用 GraphScope 来进行简单地绘制图

import graphscope.nx as nx
# 创建一个5个点的 star graph
G = nx.star_graph(5)
# 使用 nx.draw 绘制图
nx.draw(G, with_labels=True)


本小结通过一些简单的例子展示了 GraphScope 对于 NetworkX 接口的兼容性以及一些图操作和分析接口的使用。更详细的使用可以参考 GraphScope 文档

GraphScope 相对 NetworkX 算法性能上有着数量级的提升

GraphScope 支持了部分 NetworkX 内置的图算法,我们可以通过 NetworkX 的调用算法的方式来调用这些算法。下面我们通过一个简单的实验来看一下 GraphScope 对比 NetworkX 在算法性能上到底提升多少。

这个实验使用来自 snap 的 twitter 图数据, 测试算法是 NetworkX 内置的 Clustering 算法。实验所用的机器配置为8核CPU, 16G内存。

我们首先准备下数据,使用 wget 将数据集下载到本地

wget https://raw.githubusercontent.com/GraphScope/gstest/master/twitter.e ${HOME}/twitter.e

接着我们分别使用 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('$HOME/twitter.e'),
     nodetype=int,
     data=False,
     create_using=nx.Graph
)
type(g1)
# networkx.classes.graph.Graph

# 使用 GraphScope 载入 snap-twitter 图数据
g2 = gs_nx.read_edgelist(
     os.path.expandvars('$HOME/twitter.e'),
     nodetype=int,
     data=False,
     create_using=gs_nx.Graph
)
type(g2)
# graphscope.nx.classes.graph.Graph

最后我们使用 Clustering 算法来对图进行聚类分析,来看一下 GraphScope 对比 NetworkX 在算法性能上有多少提升

%%time
# 使用 GraphScope 计算图中每个点的聚类系数
ret_gs = gs_nx.clustering(g2)
# CPU times: user 213 ms, sys: 163 ms, total: 376 ms
# Wall time: 2.9 s

%%time
# 使用 NetworkX 计算图中每个点的聚类系数
ret_nx = nx.clustering(g1)
# CPU times: user 54.8 s, sys: 0 ns, total: 54.8 s
# Wall time: 54.8 s

# 对比下两者的结果是否一致
ret_gs == ret_nx
# True

从实验结果我们可以看到,GraphScope 在兼容 NetworkX 接口的同时,内置的算法对比 NetworkX 可以达到几个数量级的性能提升。GraphScope 在提供兼容 NetworkX 简单易用的接口的同时,也能提供非常高效的算法分析。

结语

本文介绍了如何让 GraphScope 使用 NetworkX 风格的方式对图数据进行操作和分析,同时,本文也通过在snap-twitter 图数据上聚类算法分析的对比来展示了 GraphScope 在兼容 NetworkX 接口的同时,提供了高效的算法分析能力。

在后续的文章中,我们将会通过 benchmark 的方式更细致地对比 GraphScope 与 NetworkX 在图操作,图查询和图分析上的一些性能比较,以及使用 GraphScope 来执行一些 github 社区中基于 NetworkX 的有趣的数据分析项目。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,386评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,142评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,704评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,702评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,716评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,573评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,314评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,230评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,680评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,873评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,991评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,706评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,329评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,910评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,038评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,158评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,941评论 2 355

推荐阅读更多精彩内容