【发布时间】: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