首页 > 解决方案 > 有没有办法更快地运行这个 Python 片段?

问题描述

from collections import defaultdict
dct = defaultdict(list)
for n in range(len(res)):
    for i in indices_ordered:
        dct[i].append(res[n][i])

请注意,这res是一个长度为 5000 的 pandas 系列列表,indices_ordered也是一个长度为 20000 的字符串列表。在我的 Mac(2.3 GHz Intel Core i5 和 16 GB 2133 MHz LPDDR3)中运行此代码需要 23 分钟。我对 Python 还很陌生,但我觉得更聪明的编码(可能更少循环)会有很大帮助。


编辑:

这是一个如何创建数据 (resindices_ordered) 以便能够在代码片段之上运行的示例(稍微更改为访问唯一字段而不是字段名称,因为我找不到如何使用字段名称构建内联系列)

import random, string, pandas
index_sz = 20000
res_sz = 5000
indices_ordered = [''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(10)) for i in range(index_sz)]
res = [pandas.Series([random.randint(0,10) for i in range(index_sz)], index = random.sample(indices_ordered, index_sz)) for i in range(res_sz)]

标签: pythonloopsdictionaryseries

解决方案


indices_ordered这里的问题是您对每个值进行迭代。只是下降indices_ordered。以数量级将其剥离测试时间:

import random
import string

import numpy as np
import pandas as pd

from collections import defaultdict


index_sz = 200
res_sz = 50
indices_ordered = [''.join(random.choice(string.ascii_uppercase + string.digits)
                   for _ in range(10)) for i in range(index_sz)]

res = [pd.Series([random.randint(0,10) for i in range(index_sz)],
                  index = random.sample(indices_ordered, index_sz))
       for i in range(res_sz)]


def your_way(res, indices_ordered):
    dct = defaultdict(list)
    for n in range(len(res)):
        for i in indices_ordered:
            dct[i].append(res[n][i])


def my_way(res):
    dct = defaultdict(list)
    for item in res:
        for string_item, value in item.iteritems():
            dct[string_item].append(value)

给出:

%timeit your_way(res, indices_ordered)
160 ms ± 5.45 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit my_way(res)
6.79 ms ± 47.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

这降低了整个方法的时间复杂度,因为您不必indicies_ordered每次都经历并分配值,因此随着数据大小的增长,差异将变得更加明显。

只是增加一个数量级:

index_sz = 2000
res_sz = 500

给出:

%timeit your_way(res, indices_ordered)
17.8 s ± 999 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit my_way(res)
543 ms ± 9.07 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

推荐阅读