29

我迷上了使用 Python 和 NetworkX 来分析图表,随着我了解更多,我想使用越来越多的数据(我猜我正在成为数据迷:-)。最终我认为我的 NetworkX 图(存储为 dict 的 dict)将超过我系统上的内存。我知道我可能可以添加更多内存,但我想知道是否有办法将 NetworkX 与 Hbase 或类似解决方案集成?

我环顾四周,并没有真正找到任何东西,但我也找不到任何与允许简单的 MySQL 后端相关的东西。

这可能吗?是否存在任何允许连接到某种持久存储的东西?

谢谢!

更新:我记得在“初创企业的社交网络分析”中看到过这个主题,作者谈到了其他存储方法(包括 hbase、s3 等),但没有说明如何执行此操作或是否可能。

4

3 回答 3

48

有两种一般类型的用于存储图形的容器:

  1. 真正的图形数据库:例如Neo4JagamemnonGraphDBAllegroGraph;这些不仅存储了一个图,而且他们还理解一个图是,例如,您可以查询这些数据库,例如,从节点 X 到节点 Y 的最短路径之间有多少节点

  2. 静态图容器:Twitter 适应 MySQL 的 FlockDB 是这里最著名的示例。这些数据库可以很好地存储和检索图形;但是要查询图形本身,您必须首先从数据库中检索图形,然后使用库(例如 Python 的优秀 Networkx)来查询图形本身。

我在下面讨论的基于 redis 的图形容器属于第二类,尽管 redis 显然也非常适合第一类容器,redis-graph 证明了这一点,redis-graph是一个非常小的 python 包,用于在 redis 中实现图形数据库。

redis在这里可以很好地工作。

Redis是一个适合生产使用的重型、耐用的数据存储,但它也很简单,可以用于命令行分析。

Redis 与其他数据库的不同之处在于它具有多种数据结构类型;我在这里推荐的是哈希数据类型。使用这种 redis 数据结构,您可以非常接近地模仿“字典列表”,这是一种用于存储图形的传统模式,其中列表中的每个项目都是一个边缘字典,键控到这些边缘源自的节点。

你需要先安装redis和python客户端。DeGizmo博客有一个出色的“启动和运行”教程,其中包括安装两者的分步指南。

安装 redis 及其 python 客户端后,启动一个 redis 服务器,您可以这样做:

  • cd到你安装 redis 的目录(如果你是通过make install 安装的,则/usr/local/bin on 'nix );下一个

  • 在 shell 提示符下输入redis -server然后输入

您现在应该在 shell 窗口中看到服务器日志文件的尾部

>>> import numpy as NP
>>> import networkx as NX

>>> # start a redis client & connect to the server:
>>> from redis import StrictRedis as redis
>>> r1 = redis(db=1, host="localhost", port=6379)

在下面的片段中,我存储了一个四节点图;下面的每一行都在 redis 客户端上调用hmset并存储一个节点和连接到该节点的边(“0” => 无边,“1” => 边)。(当然,在实践中,您会在一个函数中抽象出这些重复调用;这里我将展示每个调用,因为这样可能更容易理解。)

>>> r1.hmset("n1", {"n1": 0, "n2": 1, "n3": 1, "n4": 1})
      True

>>> r1.hmset("n2", {"n1": 1, "n2": 0, "n3": 0, "n4": 1})
      True

>>> r1.hmset("n3", {"n1": 1, "n2": 0, "n3": 0, "n4": 1})
      True

>>> r1.hmset("n4", {"n1": 0, "n2": 1, "n3": 1, "n4": 1})
      True

>>> # retrieve the edges for a given node:
>>> r1.hgetall("n2")
      {'n1': '1', 'n2': '0', 'n3': '0', 'n4': '1'}

现在该图已持久化,从 redis 数据库中检索它作为 NetworkX 图。

有很多方法可以做到这一点,下面分两个*步骤*完成:

  1. 将 redis 数据库中的数据提取到邻接矩阵中,实现为 2D NumPy 数组;然后

  2. 使用 NetworkX 内置函数将其直接转换为 NetworkX 图:

简化为代码,这两个步骤是:

>>> AM = NP.array([map(int, r1.hgetall(node).values()) for node in r1.keys("*")])
>>> # now convert this adjacency matrix back to a networkx graph:
>>> G = NX.from_numpy_matrix(am)

>>> # verify that G in fact holds the original graph:
>>> type(G)
      <class 'networkx.classes.graph.Graph'>
>>> G.nodes()
      [0, 1, 2, 3]
>>> G.edges()
      [(0, 1), (0, 2), (0, 3), (1, 3), (2, 3), (3, 3)]

当你结束一个 redis 会话时,你可以像这样从客户端关闭服务器:

>>> r1.shutdown()

redis 在关闭之前保存到磁盘,因此这是确保所有写入都被持久化的好方法。

那么redis数据库在哪里呢?它以默认文件名存储在默认位置,即主目录中的dump.rdb

要更改此设置,请编辑redis.conf文件(包含在 redis 源代码分发中);转到以下开头的行:

# The filename where to dump the DB
dbfilename dump.rdb

将 dump.rdb 更改为您想要的任何内容,但保留 .rdb 扩展名。

接下来,要更改文件路径,请在 redis.conf 中找到这一行:

# Note that you must specify a directory here, not a file name

下面的行是 redis 数据库的目录位置。编辑它,让它背诵你想要的位置。保存您的修订并重命名此文件,但保留 .conf 扩展名。您可以将此配置文件存储在您希望的任何位置,只需在启动 redis 服务器时在同一行提供此自定义配置文件的完整路径和名称:

所以下次你启动一个redis服务器时,你必须这样做(在shell提示符下:

$> cd /usr/local/bin    # or the directory in which you installed redis 

$> redis-server /path/to/redis.conf

最后,Python 包索引列出了一个专门用于在 redis 中实现图形数据库的包。这个包叫做redis-graph,我没用过。

于 2012-03-10T09:54:12.150 回答
5

有一个 SQLlite3 支持的 NetworkX 实现,称为 Cloudlight。 https://www.assembla.com/spaces/cloudlight/wiki/Tutorial

于 2013-03-21T05:35:32.427 回答
1

我很想看看使用硬盘的最佳方式。过去我制作了多个图表并将它们保存为 .dot 文件。然后以某种方式将其中一些混合在内存中。虽然不是最好的解决方案。

from random import random
import networkx as nx

def make_graph():
    G=nx.DiGraph()
    N=10
    #make a random graph
    for i in range(N):
        for j in range(i):
            if 4*random()<1:
                G.add_edge(i,j)

    nx.write_dot(G,"savedgraph.dot")
    return G

try:
    G=nx.read_dot("savedgraph.dot")
except:
    G=make_graph() #This will fail if you don't use the same seed but have created the graph in the past. You could use the Singleton design pattern here.
print G.adj
于 2012-02-15T22:22:45.180 回答