假设我有
data =
[[a, a, c],
[b, c, c],
[c, b, b],
[b, a, c]]
我想得到一个列表,其中包含每列中出现次数最多的元素:result = [b, a, c]
,最简单的方法是什么?
我使用 Python 2.6.6
在统计中,您想要的称为模式。scipy 库 ( http://www.scipy.org/ ) 有一个mode
功能,在scipy.stats
.
In [32]: import numpy as np
In [33]: from scipy.stats import mode
In [34]: data = np.random.randint(1,6, size=(6,8))
In [35]: data
Out[35]:
array([[2, 1, 5, 5, 3, 3, 1, 4],
[5, 3, 2, 2, 5, 2, 5, 3],
[2, 2, 5, 3, 3, 2, 1, 1],
[2, 4, 1, 5, 4, 4, 4, 5],
[4, 4, 5, 5, 2, 4, 4, 4],
[2, 4, 1, 1, 3, 3, 1, 3]])
In [36]: val, count = mode(data, axis=0)
In [37]: val
Out[37]: array([[ 2., 4., 5., 5., 3., 2., 1., 3.]])
In [38]: count
Out[38]: array([[ 4., 3., 3., 3., 3., 2., 3., 2.]])
使用列表理解加collections.Counter()
:
from collections import Counter
[Counter(col).most_common(1)[0][0] for col in zip(*data)]
zip(*data)
将您的列表重新排列为列列表。Counter()
对象计算输入序列中出现的频率,并.most_common(1)
为我们提供最流行的元素(加上它的计数)。
如果您的输入是单个字符串,则给出:
>>> [Counter(col).most_common(1)[0][0] for col in zip(*data)]
['b', 'a', 'c']
数据是否可散列?如果是这样, acollections.Counter
会有所帮助:
[Counter(col).most_common(1)[0][0] for col in zip(*data)]
它之所以有效,是因为zip(*data)
一次转置输入数据产生 1 列。然后计数器对元素进行计数并将计数存储在字典中,并将计数作为值。 Counters
还有一个most_common
方法,它返回具有最高计数的“N”个项目的列表(从最多计数到最少计数排序)。因此,您希望获取 most_common 返回的列表中第一项中的第一个元素,这是[0][0]
来自的地方。
例如
>>> a,b,c = 'abc'
>>> from collections import Counter
>>> data = [[a, a, c],
... [b, c, c],
... [c, b, b],
... [b, a, c]]
>>> [Counter(col).most_common(1)[0][0] for col in zip(*data)]
['b', 'a', 'c']
这是一个不使用集合模块的解决方案
def get_most_common(data):
data = zip(*data)
count_dict = {}
common = []
for col in data:
for val in col:
count_dict[val] = count_dict.get(val, 0) + 1
max_count = max([count_dict[key] for key in count_dict])
common.append(filter(lambda k: count_dict[k] == max_count, count_dict))
return common
if __name__ == "__main__":
data = [['a','a','b'],
['b','c','c'],
['a','b','b'],
['b','a','c']]
print get_most_common(data)