用 GraphScope 像 NetworkX 一样做图分析
NetworkX 是 Python 上最常用的图分析包,GraphScoep 兼容 NetworkX 接口。本文中我们将分享如何用 GraphScope 像 NetworkX 一样在(大)图上进行分析。
NetworkX 是什么
NetworkX 是一个用 Python 语言开发的图论与复杂网络建模工具,它内置了常用的图与复杂网络分析算法,提供了一套简单易用的图分析接口,可以方便地进行复杂网络数据分析、仿真建模等工作。NetworkX 的接口设计十分简洁,对于作为刚进入图算法领域的小白来说,NetworkX 的接口可以帮助使用者快速建立起对图数据的感知,并且对于中小型数据集,NetworkX 的接口也是非常好上手的。
但由于 NetworkX 是基于 Python 语言开发,算法的性能并不是它的强项,而且也无法有效地处理工业级别的大规模图数据。基于这一背景,GraphScope 提供了一套兼容 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 官方文档[1]。
用 GraphScope 像 NetworkX 一样做图分析
NetworkX 官方的 NetworkX tutorial[2] 是一个 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
的绘图功能,如果未安装,需要先通过 pip install atplotlib 安装)
import graphscope.nx as nx
# 创建一个5个点的 star graph
G = nx.star_graph(5)
# 使用 nx.draw 绘制图
nx.draw(G, with_labels=True)
通过一些简单的例子,我们展示了 GraphScope 对于 NetworkX 接口的兼容性和一些图操作/分析接口的使用。更详细的使用可以参考 GraphScope 文档[3]。
GraphScope 相比 NetworkX 算法性能有着数量级的提升
GraphScope 支持了部分 NetworkX 内置的图算法,我们可以通过 NetworkX 的调用算法的方式来调用这些算法。下面我们通过一个简单的实验来看一下 GraphScope 对比 NetworkX 在算法性能上到底提升多少。
这个实验使用来自 SNAP 的 twitter[4] 图数据,测试算法是 NetworkX 内置的 Clustering[5] 算法。实验所用的机器配置为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 的有趣的数据分析项目。
本文中涉及的代码都已经在 GraphScope Playground 中,感兴趣的读者可以点击此处进入 Playground 试用这些代码。
参考资料
[1]NetworkX 官方文档: https://networkx.org/documentation/stable/index.html
[2]NetworkX tutorial: https://networkx.org/documentation/stable/tutorial.html
[3]GraphScope 文档: https://graphscope.io/docs/reference/networkx/index.html
[4]Snap-twitter: https://snap.stanford.edu/data/ego-Twitter.html
[5]Clustering 算法: https://networkx.org/documentation/stable/reference/algorithms/generated/networkx.algorithms.cluster.clustering.html#networkx.algorithms.cluster.clustering
用 GraphScope 像 NetworkX 一样做图分析的更多相关文章
- 图分析Rapids cuGraph
图分析Rapids cuGraph 英伟达(Nvidia)建立的新的开源库可能是推进分析和使图形数据库更快的秘密要素. 在Nvidia GPU上进行并行处理. Nvidia很久以前就不再只是" ...
- SpaceSyntax【空间句法】之DepthMapX学习:第一篇 数据的输入 与 能做哪些分析
两部分,1需要喂什么东西给软件,2它能干什么(输出什么东西在下一篇讲) 博客园/B站/知乎/CSDN @秋意正寒 转载请在头部附上源地址 目录:https://www.cnblogs.com/onsu ...
- 利用GSEA对基因表达数据做富集分析
image Gene Set Enrichment Analysis (GSEA) is a computational method that determines whether an a p ...
- Skynet服务热点火焰图分析
最近花了一周时间对场景服务进行热点分析,利用以前的火焰图工具做了一点微小的贡献,分享下心得(仓库地址在https://github.com/spin6lock/skynet_systemtap_set ...
- golang 使用pprof和go-torch做性能分析
软件开发过程中,项目上线并不是终点.上线后,还要对程序的取样分析运行情况,并重构现有的功能,让程序执行更高效更稳写. golang的工具包内自带pprof功能,使找出程序中占内存和CPU较多的部分功能 ...
- 用 CPI 火焰图分析 Linux 性能问题
https://yq.aliyun.com/articles/465499 用 CPI 火焰图分析 Linux 性能问题 yangoliver 2018-02-11 16:05:53 浏览1076 ...
- 异动K线2--600532做一个分析时再给大家一只个股和近日大盘的分析
http://bbs.tianya.cn/post-stocks-612892-3.shtml ————看了一页就感觉没什么太大的意义 选时重于选股 这是一条股市生存的基本法则 看看天涯真正的高手 现 ...
- NLP(十二)依存句法分析的可视化及图分析
依存句法分析的效果虽然没有像分词.NER的效果来的好,但也有其使用价值,在日常的工作中,我们免不了要和其打交道.笔者这几天一直在想如何分析依存句法分析的结果,一个重要的方面便是其可视化和它的图分析 ...
- 抓取摩拜单车API数据,并做可视化分析
抓取摩拜单车API数据,并做可视化分析 纵聊天下 百家号|04-19 15:16 关注 警告:此篇文章仅作为学习研究参考用途,请不要用于非法目的. 摩拜是最早进入成都的共享单车,每天我从地铁站下来的时 ...
随机推荐
- Python 的排序方法 sort 和 sorted 的区别
使用 sort() 或内建函数 sorted() 对列表进行排序.它们之间的区别有两点: sort() 方法是对原列表进行操作,而 sorted() 方法会返回一个新列表,不是在原来的基础上进行操作. ...
- .NET中XML序列化和反序列化常用类和用来控制XML序列化的属性总结(XmlSerializer,XmlTypeAttribute,XmlElementAttribute,XmlAttributeAttribute,XmlArrayAttribute...)
序列化和反序列化是指什么? 序列化(seriallization): 将对象转化为便于传输的数据格式, 常见的序列化格式:二进制格式,字节数组,json字符串,xml字符串.反序列化(deserial ...
- 四旋翼中的PID调节方法 | betaflight固件如何调节PID
roll横滚,pitch俯仰,yaw航向 一.PID的作用概述 1.P产生响应速度和力度,是I和D的基础 过小响应慢(虽然无震荡) 过大会产生振荡且不断发散 2.D抑制过冲和振荡,抵抗外界的突发干扰, ...
- super.getClass()方法调用?
下面程序的输出结果是多少? import java.util.Date; public class Test extends Date{ public static void main(String[ ...
- springBoot集成Elasticsearch抛出Factory method 'restHighLevelClient' threw exception; nested exception is java.lang.NoSuchFieldError: IGNORE_DEPRECATIONS
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'restHighLeve ...
- Java中如何强制类型转换
例如,当程序中需要将 double 型变量的值赋给一个 int 型变量,该如何实现呢? 显然,这种转换是不会自动进行的!因为 int 型的存储范围比 double 型的小.此时就需要通过强制类型转换来 ...
- 解释 WEB 模块?
Spring 的 WEB 模块是构建在 application context 模块基础之上,提供一个适 合 web 应用的上下文.这个模块也包括支持多种面向 web 的任务,如透明地处理 多个文件上 ...
- jdk 8 HashMap源码解读
转自:https://www.cnblogs.com/little-fly/p/7344285.html 在原来的作者的基础上,增加了本人对源代码的一些解读. 如有侵权,请联系本人 这几天学习了Has ...
- Java_lambda表达式之"stream流学习,Map学习,collect学习,Conllectors工具类学习"
Lambda表达式学习 对List<Integer> userIdList = UserList.stream().map(User::getUserId).collect(Collect ...
- C与C++的区别之函数调用堆栈
函数调用栈 1.函数参数带入(入调用方函数的栈,从右向左入栈) int fun(int a); int fun(int a, int b); int fun(int a, int b, int c); ...