1

所以这是一个大问题:

我有一份各种出版物的作者和合著者名单。此列表可能如下所示:

[[['A','uni'],[['B','uni'],['C','uni'],['D','uni'],['E','uni']]],

[['E','uni'],[['A','uni'],['F','uni'],['G','uni']]]]

因此,作者 A 与作者 B、C 和 D 合作了一个出版物,作者 E 与作者 A、F 和 G 合作了另一个出版物。

我需要的是一份所有作者的名单,即使他们只是被列为共同作者(B、C、D、F、G)以及他们与谁一起写了多少篇论文。因此,所有主要作者(A 和 E)都与他们的共同作者(A 与 B、C、D、E;E 与 A、F、G)一起工作,但论文的共同作者也一起工作(B 与 C、D、E还有 A 等等)。最重要的是,我需要知道他们一起工作了多少篇论文。

所以这个小例子的最终结果是:

[[['A','uni'],[['B','uni',1],['C','uni',1],['D','uni',1],['E','uni',2],['F','uni',1],['G','uni',1]]],

[['B','uni'],[['A','uni',1],['C','uni',1],['D','uni',1],['E','uni',1]]],

[['C','uni'],[['A','uni',1],['B','uni',1],['D','uni',1],['E','uni',1]]],

[['D','uni'],[['A','uni',1],['B','uni',1],['C','uni',1],['E','uni',1]]],

[['E','uni'],[['A','uni',2],['B','uni',1],['C','uni',1],['D','uni',1],['F','uni',1],['G','uni',1]]],

[['F','uni'],[['A','uni',1],['E','uni',1],['G','uni',1]]],

[['G','uni'],[['A','uni',1],['E','uni',1],['F','uni',1]]]]

好吧,老实说,这有点令人困惑,但我希望你明白我的意思。(uni 条目代表作者工作的大学。可能仍包含其他信息,但这与此任务无关)

我有这个初始列表,我使用我编写的用于解析数据库的 python 脚本获得。我想创建一个图表,显示我和谁以及多久写一次。

我现在玩了一段时间,我只是找不到一个好的解决方案。我想我可以写出一些有用的东西,但它不会很好或没有效率并且非常耗时。那么有没有一种快速的、pythonic 的方法来解决这个问题呢?我的示例现在只有两个出版物,但我必须分析大约 10000 个出版物,其中一些有几百个共同作者......

4

3 回答 3

1
from collections import defaultdict

L = [[['A','uni'],[['B','uni'],['C','uni'],['D','uni'],['E','uni']]],
     [['E','uni'],[['A','uni'],['F','uni'],['G','uni']]]]

res = defaultdict(set)

for x, y in L:
    x = [tuple(x)]
    y = map(tuple, y)
    row = x+y
    for i in row:
        print set(row)
        res[i] |= set(row)

for k, v in res.items():
    v.remove(k)
    print k, list(v)

输出:

('B', 'uni') [('A', 'uni'), ('D', 'uni'), ('E', 'uni'), ('C', 'uni')]
('A', 'uni') [('B', 'uni'), ('F', 'uni'), ('D', 'uni'), ('G', 'uni'), ('E', 'uni'), ('C', 'uni')]
('F', 'uni') [('A', 'uni'), ('G', 'uni'), ('E', 'uni')]
('D', 'uni') [('A', 'uni'), ('B', 'uni'), ('E', 'uni'), ('C', 'uni')]
('G', 'uni') [('A', 'uni'), ('E', 'uni'), ('F', 'uni')]
('E', 'uni') [('B', 'uni'), ('A', 'uni'), ('F', 'uni'), ('D', 'uni'), ('G', 'uni'), ('C', 'uni')]
('C', 'uni') [('A', 'uni'), ('D', 'uni'), ('B', 'uni'), ('E', 'uni')]
于 2012-10-02T20:40:01.903 回答
1

您不需要数据库,但首先需要一些数据结构来保存和表示您的所有信息。我不会写完整的类,只写它们的重要属性。

class Author(object):
    name
    university        

class Publication(object):
    name
    date

class Authorship(object)
    author
    publication
    main_author(bool)

接下来,您必须组织这些对象。Authors 和 Publications 应该是唯一的东西,因此如果您的数据集不超过数百 MB,您可以将它们分别放在普通字典中。它们必须由唯一属性索引。如果 author.name 还不够,请使用大学和作者姓名的元组,或者更好的生日或与作者相关的内容(如果有的话),因为大学可能会改变。

对于作者身份,您应该创建不同的索引,这样您就可以更快地搜索,而无需一直遍历整个列表。也许你想要一些 defaultdict(list),由包含他们出版物的作者索引,否则另一个 defaultdict(list),用出版物索引。注意保持一致性(重复,数据错误可能很残酷)。

之后,您只需遍历您的数据集并填充您的结构。

于 2012-10-02T20:44:17.920 回答
1

我的版本:

from collections import defaultdict
from collections import Counter
from itertools import chain

L = [[['A', 'uni'], [['B', 'uni'], ['C', 'uni'], ['D', 'uni'], ['E', 'uni']]], [['E', 'uni'], [['A', 'uni'], ['F', 'uni'], ['G', 'uni']]]]

d = defaultdict(Counter)
for publication in L:
    authors = [tuple(a) for a in chain([publication[0]], publication[1])]
    for author in authors:
        d[author].update(authors)

for k, v in d.iteritems():
    print k, [(author[0], author[1], counter)
              for author, counter in v.iteritems() if author[0] != k[0]]

输出:

('B', 'uni') [('A', 'uni', 1), ('D', 'uni', 1), ('E', 'uni', 1), ('C', 'uni', 1)]
('A', 'uni') [('B', 'uni', 1), ('F', 'uni', 1), ('D', 'uni', 1), ('G', 'uni', 1), ('E', 'uni', 2), ('C', 'uni', 1)]
('F', 'uni') [('A', 'uni', 1), ('G', 'uni', 1), ('E', 'uni', 1)]
('D', 'uni') [('A', 'uni', 1), ('B', 'uni', 1), ('E', 'uni', 1), ('C', 'uni', 1)]
('G', 'uni') [('A', 'uni', 1), ('E', 'uni', 1), ('F', 'uni', 1)]
('E', 'uni') [('B', 'uni', 1), ('A', 'uni', 2), ('F', 'uni', 1), ('D', 'uni', 1), ('G', 'uni', 1), ('C', 'uni', 1)]
('C', 'uni') [('A', 'uni', 1), ('D', 'uni', 1), ('B', 'uni', 1), ('E', 'uni', 1)]
于 2012-10-02T20:47:16.797 回答