如何获取float数组元素的出现次数?
如果数组是
[-1,2,3-,-1,3,4,4,4,4,4],
结果应该是
[2,1,2,5],
不一定按照这个顺序,并且不需要从计数到计数的元素的映射,只计算重要性。
numpy.histogram会做类似的事情,但它必须使用bin,这需要预先计算bin-size来分隔元素,并且还可以创建不必要的许多空bin。
这也可以使用散列或排序手动完成,但是 似乎应该有一个没有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
答案 0 :(得分: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+)将为您提供可迭代的映射。
答案 1 :(得分:4)
如果你想要一个笨拙的解决方案:
>>> 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
答案 2 :(得分:0)
不确定这是否是最优雅的解决方案,但您可以使用这个衬垫:
import numpy
aa = [-1,2,3,-1,3,4,4,4,4,4]
histogr = [aa.count(i) for i in numpy.unique(aa)]