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

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

当前回答

Python 2.7+引入了字典理解。从列表中构建字典将获得计数并去除重复项。

>>> a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
>>> d = {x:a.count(x) for x in a}
>>> d
{1: 4, 2: 4, 3: 2, 4: 1, 5: 2}
>>> a, b = d.keys(), d.values()
>>> a
[1, 2, 3, 4, 5]
>>> b
[4, 4, 2, 1, 2]

其他回答

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

>>> 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)。如果是负数,结果会很奇怪。

另一种方法是使用较重但功能强大的库——NLTK。

import nltk

fdist = nltk.FreqDist(a)
fdist.values()
fdist.most_common()

通过遍历列表并计算它们,手动计算出现的数量,使用collections.defaultdict跟踪到目前为止看到的内容:

from collections import defaultdict

appearances = defaultdict(int)

for curr in a:
    appearances[curr] += 1

你可以这样做:

import numpy as np
a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
np.unique(a, return_counts=True)

输出:

(array([1, 2, 3, 4, 5]), array([4, 4, 2, 1, 2], dtype=int64))

第一个数组是值,第二个数组是具有这些值的元素的数量。

所以如果你想要得到一个数字数组,你应该使用这个:

np.unique(a, return_counts=True)[1]
a=[1,2,3,4,5,1,2,3]
b=[0,0,0,0,0,0,0]
for i in range(0,len(a)):
    b[a[i]]+=1