在Python中从2D数组中选择列的最快方法?

时间:2012-12-03 22:53:38

标签: python performance

我正在尝试提高函数的性能,该函数计算Python中2D数组的某个元素的出现次数。时间来自cProfile,它也告诉我count()每357595次呼叫仅需要〜0.08。

for循环最快(357595次调用时为.375s):

def count_column(grid, j, element):
    count = 0
    for x in range(0, len(grid)):
        if grid[x][j] == element:
            count += 1
    return count

列表理解的速度可以忽略不计(357595次呼叫为.400s):

def count_column(grid, j, element):
    return [x[j] for x in grid].count(element)

Zip是最大的一个边缘(357595次呼叫为.741s):

def validate_column(grid, j, element):
    return zip(*grid)[j].count(element)

有没有更快的方法可以做到这一点,或者最好的办法是用chain.from_iterable来平整数组?

2 个答案:

答案 0 :(得分:1)

这是我获得的一系列不同变体的时间:

cc_explicit 5000 0.00290012359619
cc_explicit_xrange 5000 0.00145506858826
cc_filter 5000 0.00117516517639
cc_genexp 5000 0.00100994110107
cc_ifilter 5000 0.00170707702637
cc_izip 1 3.21103000641
cc_listcomp 5000 0.000788927078247
cc_zip 5000 12.1080589294

代码和测试驱动程序位于http://pastebin.com/WSAUqTyv

由于zip和izip非常慢,我把它们从等式中拿出来并用其余的方式进行500000x10测试:

cc_explicit 500000 0.105982065201
cc_explicit_xrange 500000 0.103507995605
cc_filter 500000 0.0856108665466
cc_genexp 500000 0.0679898262024
cc_ifilter 500000 0.144966125488
cc_listcomp 500000 0.0396680831909

因此,最快的解决方案是listcomp。但是,当我将随机数据和较大的行放在其上时,genexpexplicit_xrange有时会超过listcomp,并且在大多数测试中它们都非常接近,{{1}使用更少的内存,所以我会选择:

genexp

答案 1 :(得分:0)

如果我能在这里提供两分钱,你也应该按照已经建议的那样研究 Numpy 。或者,如果您不想处理非标准库,则应该查看collections.Counter()。是的,它带来了大量的前期成本,但如果您发现自己在同一数据集中对很多不同的值进行计数,您可能会发现初始投资得到回报。