【问题标题】:Is there any way to make this code faster?有没有办法让这段代码更快?
【发布时间】:2019-05-03 04:48:58
【问题描述】:

我有一个 pandas 数据框,其中包含一些具有大约 400 万条记录的论文的详细信息。我需要找到该数据集中发表文章数量最多的前 50 位作者。我有两个包含这些数据的文件,所以我必须将它们都读入数据帧并将它们附加在一起以获得一个可以使用的数据帧。我只使用了数据框中的作者列,因为还有 32 个其他列不需要。

到目前为止,我已经提出了以下解决方案。此外,这是一个算法分配,所以我不能使用任何内置算法。目前,我正在使用字典来存储每个作者的发表次数,然后循环遍历字典以获取发表次数最多的作者。此外,单行中可以有多个作者,例如 'Auth 1 |授权 2 |授权 3|'这就是我拆分字符串的原因。

我想知道是否有更快的方法来完成所有这些。有什么方法可以在数据帧循环期间找到最大值?同样,我不允许使用内置算法进行搜索或排序。任何建议都会有所帮助。

谢谢。

start_time = ti.default_timer()

only_authors_article = pd.DataFrame(articles['author'])
only_authors_inproceedings = pd.DataFrame(proceedings['author'])
all_authors = only_authors_article.append(only_authors_inproceedings, ignore_index = True)
all_authors = all_authors.dropna(how = 'any')

auth_dict = defaultdict(int)

for auth_list in zip(all_authors['author']):
    auth_list = auth_list[0]

    if '|' in auth_list:
        auths = auth_list.split('|')

        for auth in auths:
            auth_dict[auth] += 1
    else:
        auth_dict[auth_list] += 1


most_pub_authors = []

for i in range(0, 50):
    max_pub_count = 0
    max_pub_auth = None

    for author, pub_count in auth_dict.items(): 
        if pub_count > max_pub_count:
            max_pub_count = pub_count
            max_pub_auth = author

    most_pub_authors.append( (max_pub_auth, max_pub_count) ) 
    del auth_dict[max_pub_auth]

print(most_pub_authors) 


elapsed_time = ti.default_timer() - start_time
print("Total time taken: " + str(elapsed_time))

编辑 1:来自 all_authors 的一些示例数据

    author
0   Sanjeev Saxena
1   Hans Ulrich Simon
2   Nathan Goodman|Oded Shmueli
3   Norbert Blum
4   Arnold Schönhage
5   Juha Honkala
6   Christian Lengauer|Chua-Huang Huang
7   Alain Finkel|Annie Choquet
8   Joachim Biskup
9   George Rahonis|Symeon Bozapalidis|Zoltán Fülöp...
10  Alex Kondratyev|Maciej Koutny|Victor Khomenko|...
11  Wim H. Hesselink
12  Christian Ronse
13  Carol Critchlow|Prakash Panangaden
14  Fatemeh Ghassemi|Ramtin Khosravi|Rosa Abbasi
15  Robin Milner
16  John Darlington
17  Giuseppe Serazzi|M. Italiani|Maria Calzarossa
18  Vincent Vajnovszki
19  Christian Stahl|Richard Müller 0001|Walter Vogler
20  Luc Devroye
21  K. C. Tan|T. C. Hu
22  William R. Franta
23  Ekkart Kindler
24  Demetres D. Kouvatsos
25  Christian Lengauer|Sergei Gorlatch
26  Roland Meyer
27  Stefan Reisch
28  Erzsébet Csuhaj-Varjú|Victor Mitrana
29  Lila Kari|Manasi S. Kulkarni

【问题讨论】:

  • 根据this question 中的答案,似乎使用.items() 进行迭代是最慢的方法
  • 我尝试了“for author, pub_count in list(auth_dict.items())”,但它比以前多花了大约 2 秒。谢谢你的建议
  • 您能发布一个数据示例吗?
  • 这两个部分中哪一个花费的时间最长?
  • 我构建字典的第一个 for 循环需要更长的时间

标签: python pandas algorithm performance dataframe


【解决方案1】:

问题出在这部分:

for i in range(0, 50):
    . . .
    for author, pub_count in auth_dict.items(): 
        . . .

迭代整个数据集 50 次。

你可以做的是累加器方法:有一个前 50 位作者的列表,最初由前 50 位作者填充,然后迭代 auth_dict 一次,如果你发现一个高于那个。

类似这样的:

top_authors = []
lowest_pub_count = 0
top_n = 50
for author, pub_count in auth_dict.items():
    if pub_count > lowest_pub_count:        # found element that is larger than the smallest in top-N so far
        if len(top_authors) < top_n:        # not reached N yet - just append to the list
            top_authors.append([author, pub_count])
            if len(top_authors) < top_n:    # keep lowest_pub_count at 0 until N is reached
                continue
        else:                               # replace the lowest element with the found one
            for i in range(len(top_authors)):
                if top_authors[i][1] == lowest_pub_count:
                    top_authors[i] = [author, pub_count]
                    break
        lowest_pub_count = pub_count
        for i in range(len(top_authors)):   # find the new lowest element
            if top_authors[i][1] < lowest_pub_count:
                lowest_pub_count = top_authors[i][1]

对前 50 个列表中最低元素的顺序搜索由于不频繁进行而被摊销。

【讨论】:

  • 我试过了,它确实运行得更快!非常感谢!
【解决方案2】:
auth_dict = defaultdict(int)

for auth_list in zip(all_authors['author']):
    auth_list = auth_list[0]

    if '|' in auth_list:
        auths = auth_list.split('|')

        for auth in auths:
            auth_dict[auth] += 1
    else:
        auth_dict[auth_list] += 1

是一种复杂的书写方式

auth_dict = defaultdict(int)

for auth_list in all_authors['author']:
    for auth in auth_list.split('|'):
        auth_dict[auth] += 1

这可能会更快:

Counter(itertools.chain.from_iterable(
    auth_list.split('|') for auth_list in all_authors['author']))

其中itertoolsimport itertoolsCounterfrom collections import Counter


most_pub_authors = []

for i in range(0, 50):
    max_pub_count = 0
    max_pub_auth = None

    for author, pub_count in auth_dict.items(): 
        if pub_count > max_pub_count:
            max_pub_count = pub_count
            max_pub_auth = author

    most_pub_authors.append( (max_pub_auth, max_pub_count) ) 
    del auth_dict[max_pub_auth]

print(most_pub_authors)

遍历整个 dict 相当多次。试一试:

most_pub_authors = heapq.nlargest(50, auth_dict.items(), key=itemgetter(1))

其中itemgetterfrom operator import itemgetter

【讨论】:

  • I'm not permitted to use inbuilt algorithms for searching or sorting. Any suggestions would help.
  • 用堆重新实现 heapq.nlargest,我猜
  • 我想我可以试试。感谢您的帮助!
猜你喜欢
  • 2021-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-22
  • 1970-01-01
  • 2020-03-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多