给定一个无序的值列表,比如

a = [5, 1, 2, 2, 4, 3, 1, 2, 3, 1, 1, 5, 2]

我怎样才能得到出现在列表中的每个值的频率,就像这样?

# `a` has 4 instances of `1`, 4 of `2`, 2 of `3`, 1 of `4,` 2 of `5`
b = [4, 4, 2, 1, 2] # expected output

当前回答

from collections import OrderedDict
a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
def get_count(lists):
    dictionary = OrderedDict()
    for val in lists:
        dictionary.setdefault(val,[]).append(1)
    return [sum(val) for val in dictionary.values()]
print(get_count(a))
>>>[4, 4, 2, 1, 2]

删除副本并维持秩序:

list(dict.fromkeys(get_count(a)))
>>>[4, 2, 1]

其他回答

在Python 2.7(或更新版本)中,可以使用集合。计数器:

>>> import collections
>>> a = [5, 1, 2, 2, 4, 3, 1, 2, 3, 1, 1, 5, 2]
>>> counter = collections.Counter(a)
>>> counter
Counter({1: 4, 2: 4, 5: 2, 3: 2, 4: 1})
>>> counter.values()
dict_values([2, 4, 4, 1, 2])
>>> counter.keys()
dict_keys([5, 1, 2, 4, 3])
>>> counter.most_common(3)
[(1, 4), (2, 4), (5, 2)]
>>> dict(counter)
{5: 2, 1: 4, 2: 4, 4: 1, 3: 2}
>>> # Get the counts in order matching the original specification,
>>> # by iterating over keys in sorted order
>>> [counter[x] for x in sorted(counter.keys())]
[4, 4, 2, 1, 2]

如果您使用的是Python 2.6或更老版本,可以在这里下载实现。

def frequencyDistribution(data):
    return {i: data.count(i) for i in data}   

print frequencyDistribution([1,2,3,4])

...

 {1: 1, 2: 1, 3: 1, 4: 1}   # originalNumber: count

计算元素的频率可能最好使用字典:

b = {}
for item in a:
    b[item] = b.get(item, 0) + 1

要删除重复项,请使用set:

a = list(set(a))

对于您的第一个问题,迭代列表并使用字典跟踪元素的存在。

对于你的第二个问题,只需使用集合操作符。

郑重声明,一个实用的答案:

>>> L = [1,1,1,1,2,2,2,2,3,3,4,5,5]
>>> import functools
>>> >>> functools.reduce(lambda acc, e: [v+(i==e) for i, v in enumerate(acc,1)] if e<=len(acc) else acc+[0 for _ in range(e-len(acc)-1)]+[1], L, [])
[4, 4, 2, 1, 2]

如果你把0也算进去,那就更简洁了:

>>> functools.reduce(lambda acc, e: [v+(i==e) for i, v in enumerate(acc)] if e<len(acc) else acc+[0 for _ in range(e-len(acc))]+[1], L, [])
[0, 4, 4, 2, 1, 2]

一个解释:

我们从一个空的acc列表开始; 如果L的下一个元素e小于acc的大小,我们只需更新这个元素:如果acc的索引i是当前元素e,则v+(i==e)表示v+1,否则为之前的值v; 如果L的下一个元素e大于或等于acc的大小,我们必须展开acc以容纳新的1。

元素不必排序(itertools.groupby)。如果是负数,结果会很奇怪。