【问题标题】:Get network edges from SQL tables for networkX in python从 python 中 networkX 的 SQL 表中获取网络边缘
【发布时间】:2017-02-01 19:43:46
【问题描述】:

我正在尝试从标准化的 SQLite 数据库中获取网络边缘的数量,该数据库已标准化如下:

 Authors                    Paper                      Paper_Authors
 | authorID | name | etc    | paperID | title | etc    | paperID  | authorID |
 |    1     | .... | ...    |    1    | ..... | ...    |    1     |    1     |
 |    2     | .... | ...    |    2    | ..... | ...    |    1     |    2     |
 |    3     | .... | ...    |    .    | ..... | ...    |    1     |    3     | 
 |    4     | .... | ...    |  60,000 | ..... | ...    |    2     |    1     |
 |    5     | .... | ...                               |    2     |    4     |
 |    .     | .... | ...                               |    2     |    5     |
 | 120,000  | .... | ...                               |    .     |    .     |
                                                       |  60,000  | 120,000  | 

大约有 120,000 位作者和 60,000 篇论文,索引表大约有 250,000 行。

我正在尝试将其放入 networkX 进行一些连通性分析,输入节点很简单:

 conn = sqlite3.connect('../input/database.sqlite')
 c = conn.cursor()
 g = nx.Graph()
 c.execute('SELECT authorID FROM Authors;')
 authors = c.fetchall()
 g.add_nodes_from(authors) 

我遇到的问题来自于尝试确定要馈送到 networkX 的边,这需要连接两个节点的元组中的值,以上面的数据为例;

 [(1,1),(1,2),(1,3),(2,3),(1,4),(1,5),(4,5)]

将描述上面的数据集。

我有以下代码,它有效,但不优雅:

 def coauthors(pID):
     c.execute('SELECT authorID \
                FROM Paper_Authors \
                WHERE paperID IS ?;', (pID,))
     out = c.fetchall()
     g.add_edges_from(itertools.product(out, out))

 c.execute('SELECT COUNT() FROM Papers;')
 papers = c.fetchall()

 for i in range(1, papers[0][0]+1):
     if i % 1000 == 0:
         print('On record:', str(i))
     coauthors(i)

这通过遍历数据库中的每篇论文,返回作者列表并迭代地制作作者组合元组列表并将它们以零碎的方式添加到网络中,这很有效,但需要 30 到 45 分钟:

 print(nx.info(g))
 Name: 
 Type: Graph
 Number of nodes: 120670
 Number of edges: 697389
 Average degree:  11.5586

所以我的问题是,有没有更优雅的方法来获得相同的结果,理想情况下使用 paperID 作为边缘标签,以便更轻松地在 networkX 之外导航网络。

【问题讨论】:

  • 网络不是直接由Paper_Authors中的行定义的吗?您显示的元组列表与示例数据有什么关系?
  • @CL。不幸的是不是,因为networkx似乎要求定义边缘的元组采用edge = (node, node)格式,所以在这种情况下paper = (author, author),使用Paper_Authors数据将采用edge = (author, paper)格式,除非有办法定义两种节点,然后以某种方式折叠网络。
  • @CL。对此进行了更多调查,如果我给作者和论文一个不同的前缀并且基本上有两种不同类型的节点,一种用于论文,一种用于作者,它确实有效。

标签: python sql sqlite networkx


【解决方案1】:

您可以通过自连接获得每篇论文的所有作者组合:

SELECT paperID,
       a1.authorID AS author1,
       a2.authorID AS author2
FROM Paper_Authors AS a1
JOIN Paper_Authors AS a2 USING (paperID)
WHERE a1.authorID < a2.authorID;         -- prevent duplicate edges

除非您在paperID 或更好的covering index 上同时在paperIDauthorID 或更好的WITHOUT ROWID table 上都有索引,否则这将非常低效。

【讨论】:

  • 非常感谢,这运行得很完美,在大约 600,000 个输出行上只用了大约 2 秒,我也会看看其他加速。非常感谢您的回答,我的想法是如何选择 authorID,而我已经在选择 authorID。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-09-10
  • 1970-01-01
  • 2013-03-16
  • 1970-01-01
  • 2022-12-16
  • 2015-05-20
  • 2021-06-03
相关资源
最近更新 更多