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_nodeadd_nodes_from来添加节点,通过add_edgeadd_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_nodesnumber_of_edges来获取图点和边的数量,通过nodesedges,adjdegree等接口来获取图当前的点和边,以及点的邻居和度数等信息。

# 查询目前图中点和边的数目
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_noderemove_nodes_from来删除图中的节点,通过remove_edgeremove_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 一样做图分析的更多相关文章

  1. 图分析Rapids cuGraph

    图分析Rapids cuGraph 英伟达(Nvidia)建立的新的开源库可能是推进分析和使图形数据库更快的秘密要素. 在Nvidia GPU上进行并行处理. Nvidia很久以前就不再只是" ...

  2. SpaceSyntax【空间句法】之DepthMapX学习:第一篇 数据的输入 与 能做哪些分析

    两部分,1需要喂什么东西给软件,2它能干什么(输出什么东西在下一篇讲) 博客园/B站/知乎/CSDN @秋意正寒 转载请在头部附上源地址 目录:https://www.cnblogs.com/onsu ...

  3. 利用GSEA对基因表达数据做富集分析

      image Gene Set Enrichment Analysis (GSEA) is a computational method that determines whether an a p ...

  4. Skynet服务热点火焰图分析

    最近花了一周时间对场景服务进行热点分析,利用以前的火焰图工具做了一点微小的贡献,分享下心得(仓库地址在https://github.com/spin6lock/skynet_systemtap_set ...

  5. golang 使用pprof和go-torch做性能分析

    软件开发过程中,项目上线并不是终点.上线后,还要对程序的取样分析运行情况,并重构现有的功能,让程序执行更高效更稳写. golang的工具包内自带pprof功能,使找出程序中占内存和CPU较多的部分功能 ...

  6. 用 CPI 火焰图分析 Linux 性能问题

    https://yq.aliyun.com/articles/465499 用 CPI 火焰图分析 Linux 性能问题   yangoliver 2018-02-11 16:05:53 浏览1076 ...

  7. 异动K线2--600532做一个分析时再给大家一只个股和近日大盘的分析

    http://bbs.tianya.cn/post-stocks-612892-3.shtml ————看了一页就感觉没什么太大的意义 选时重于选股 这是一条股市生存的基本法则 看看天涯真正的高手 现 ...

  8. NLP(十二)依存句法分析的可视化及图分析

      依存句法分析的效果虽然没有像分词.NER的效果来的好,但也有其使用价值,在日常的工作中,我们免不了要和其打交道.笔者这几天一直在想如何分析依存句法分析的结果,一个重要的方面便是其可视化和它的图分析 ...

  9. 抓取摩拜单车API数据,并做可视化分析

    抓取摩拜单车API数据,并做可视化分析 纵聊天下 百家号|04-19 15:16 关注 警告:此篇文章仅作为学习研究参考用途,请不要用于非法目的. 摩拜是最早进入成都的共享单车,每天我从地铁站下来的时 ...

随机推荐

  1. [八省联考2018]制胡窜 (SAM+大讨论)

    正着做着实不太好做,正难则反,考虑反着做. 把i,j看成在切割字符串,我们统计有多少对(i,j)会切割所有与\(s_{l,r}\)相同的串.对于在后缀自动机上表示\(s_{l,r}\)的节点x,x的p ...

  2. KestrelServer详解[1]:注册监听终结点(Endpoint)

    具有跨平台能力的KestrelServer是最重要的服务器类型.针对KestrelServer的设置均体现在KestrelServerOptions配置选项上,注册的终结点是它承载的最重要的配置选项. ...

  3. Redis常见问题及其场景问题

    假如 Redis 里面有 1 亿个 key,其中有 10w 个 key 是以 某个固定的已知的前缀开头的,如果将它们全部找出来?   使用 keys 指令可以扫出指定模式的 key 列表. 对方接着追 ...

  4. 为什么Java中不支持多重继承?

    我发现这个 Java 核心问题很难回答,因为你的答案可能不会让面试官满意,在大多数情况下,面试官正在寻找答案中的关键点,如果你提到这些关键点,面试官会很高兴.在 Java 中回答这种棘手问题的关键是准 ...

  5. 什么是 YAML?

    YAML 是一种人类可读的数据序列化语言.它通常用于配置文件. 与属性文件相比,如果我们想要在配置文件中添加复杂的属性,YAML 文件就更加 结构化,而且更少混淆.可以看出 YAML 具有分层配置数据 ...

  6. Kafka 分区数可以增加或减少吗?为什么?

    我们可以使用 bin/kafka-topics.sh 命令对 Kafka 增加 Kafka 的分区数据,但是 Kafka 不支持减少分区数. Kafka 分区数据不支持减少是由很多原因的,比如减少的分 ...

  7. uWSGI+django+nginx的工作原理流程与部署

    二.必要的前提 2.1 准备知识 django 一个基于python的开源web框架,请确保自己熟悉它的框架目录结构. uWSGI 一个基于自有的uwsgi协议.wsgi协议和http服务协议的web ...

  8. 启动一个线程是调用 run()还是 start()方法?

    启动一个线程是调用 start()方法,使线程所代表的虚拟处理机处于可运行状态, 这意味着它可以由 JVM 调度并执行,这并不意味着线程就会立即运行.run()方 法是线程启动后要进行回调(callb ...

  9. Eureka server

    Eureka server使用的不是spring mvc的框架,而是使用Jersey. Eureka server ,启动的流程,追本溯源,是在 DiscoveryClient里面,使用这个构造方法 ...

  10. 学习Cobbler(一)

    一. http://cobbler.github.io/ Cobbler is a Linux installation server that allows for rapid setup of n ...