2

如何获取浮点数组元素的出现次数?如果数组是[-1,2,3,-1,3,4,4,4,4,4],
结果应该是[2,1,2,5],不一定是这个顺序,并且不需要从计数映射到被计数的元素,只需要计数即可。

numpy.histogram 会做类似的事情,但它必须使用 bins,这需要预先计算 bin-size 来分离元素,并且还可能创建不必要的许多空 bins。

这也可以通过散列或排序手动完成,但似乎应该有一种快速、一次性的方法,无需 python 级循环。

谢谢!

编辑:

我尝试了撰写本文时建议的解决方案,并认为我会分享结果,因为它们有些出乎意料。我最初没有提到的是该流程适用于相当小的列表,但该操作被调用了数百万次,这在某种程度上是一个极端情况。

测试及其打印输出如下。histogramize1 是我想要改进其性能的原始函数。它比第二快快 x2,知道为什么会很有趣。

import numpy as np
from collections import Counter
from timeit import timeit


def histogramize1(X):
    cnts = {}
    for x in X:
        if x in cnts:
            cnts[x] += 1
        else:
            cnts[x] = 1
    lst = [ v for k,v in cnts.iteritems() ]

    lX = len(X)
    return [ float(x)/lX for x in lst ]


def histogramize2(X):

    ua,uind= np.unique(X,return_inverse=True)
    lX = len(X)    
    res = [float(x)/lX for x in np.bincount(uind)]

    return res


def histogramize3(X):
    counts = Counter(X)
    lX = len(X)
    res = [float(x)/lX for x in counts.viewvalues()]
    return res

def histogramize4(X):
    lX = len(X)
    return [float(X.count(i))/lX for i in np.unique(X)]

if __name__ == '__main__':

    lst0 = [-1,2,3,-1,3,4,4,4,4,4]
    lst = lst0 + lst0 + lst0 + lst0

    num = 100000
    print timeit("histogramize1(lst)",setup="from __main__ import histogramize1, lst",number=num)
    print timeit("histogramize2(lst)",setup="from __main__ import histogramize2, lst",number=num)
    print timeit("histogramize3(lst)",setup="from __main__ import histogramize3, lst",number=num)
    print timeit("histogramize4(lst)",setup="from __main__ import histogramize4, lst",number=num)

这打印:

1.35243415833

10.0806729794

2.89171504974

15.5577590466

4

3 回答 3

5

对于 Python 2.7+:

>>> from collections import Counter
>>> counts = Counter([-1,2,3,-1,3,4,4,4,4,4])
>>> counts.viewvalues() # counts.values() in Python 3+
dict_values([1, 2, 5, 2])

http://docs.python.org/library/collections.html#collections.Counter(不过,如果您坚持使用旧版本,则有 2.4 和 2.5 的实现。)

并且由于Counter是 的子类,因此如果您需要它们dict,您可以获得计算的值。counts.viewitems()(2.7) 或counts.items()(3+) 将为您提供可迭代的映射。

于 2013-08-02T12:48:31.477 回答
4

如果您确实想要一个 numpy 解决方案:

>>> a=np.array( [-1,2,3,-1,3,4,4,4,4,4])
>>> ua,uind=np.unique(a,return_inverse=True)

#This returns the unique values and indices of those values.
>>> ua
array([-1,  2,  3,  4])
>>> uind
array([0, 1, 2, 0, 2, 3, 3, 3, 3, 3])

>>> np.bincount(uind)
array([2, 1, 2, 5])

这具有显示什么计数与什么数字相关的额外好处。

小型阵列的启动速度要快两倍多:

import numpy as np
from collections import Counter

a=np.random.randint(0,100,(500))
alist=a.tolist()

In [27]: %timeit  Counter(alist).viewvalues()
1000 loops, best of 3: 209 us per loop

In [28]: %timeit ua,uind=np.unique(a,return_inverse=True);np.bincount(uind)
10000 loops, best of 3: 85.8 us per loop
于 2013-08-02T14:32:17.797 回答
0

不确定这是否是最优雅的解决方案,但你可以使用这个 oneliner:

import numpy
aa = [-1,2,3,-1,3,4,4,4,4,4]
histogr = [aa.count(i) for i in numpy.unique(aa)]
于 2013-08-02T13:43:06.383 回答