我分析了一些非常密切聚类的数字时间测量。我想获得平均值,标准偏差等。有些输入很大,所以我想我可以避免创建数百万个数字的列表而是 使用Python collections.Counter对象作为紧凑表示。
示例:我的一个小输入产生collection.Counter
,如[(48, 4082), (49, 1146)]
,这意味着值48的4,082次出现和值49的1,146次出现。对于此数据集,我手动计算平均值为类似于48.2192042846。
当然,如果我有一个4,082 + 1,146 = 5,228个整数的简单列表,我会把它提供给numpy.mean()。
我的问题:如何根据collections.Counter
对象中的值计算描述性统计信息,就像我有一个数字列表一样?我是否必须创建完整列表或是否有快捷方式?
答案 0 :(得分:6)
collections.Counter()
是dict
的子类。只需使用Counter().values()
获取计数列表:
counts = Counter(some_iterable_to_be_counted)
mean = numpy.mean(counts.values())
请注意,我在此处不调用Counter.most_common()
,这将生成您在问题中发布的(key, count)
元组列表。
如果您必须使用Counter.most_common()
的输出,则可以使用列表理解过滤掉计数:
mean = numpy.mean([count for key, count in most_common_list])
如果您使用的是Python 3(其中dict.values()
返回字典视图),您可以传入list(counts.values())
,也可以使用标准库staticstics.mean()
function,这需要一个可迭代的(包括dict.values()
字典视图)。
如果您打算计算平均键值按其计数加权,您可以直接从计数器值进行自己的计算。在Python 2中,它是:
from __future__ import division
mean = sum(key * count for key, count in counter.iteritems()) / sum(counter.itervalues())
from __future__
导入应位于模块的顶部,并确保您不会遇到大浮点数的溢出问题。在Python 3中,它将被简化为:
mean = sum(key * count for key, count in counter.items()) / sum(counter.values())
中位数可以用二分法计算;按键对(key, count)
对进行排序,对计数求和,并将中间点平分为计数的累计和。插入点的索引指向排序键列表中的中间键。
答案 1 :(得分:3)
虽然您可以在创建值列表后将所有内容卸载到numpy
,但这比所需要的要慢。相反,您可以使用您需要的实际定义。
均值只是所有数字的总和除以它们的数量,因此非常简单:
sum_of_numbers = sum(number*count for number, count in counter)
count = sum(count for n, count in counter)
mean = sum_of_numbers / count
标准偏差有点复杂。它是方差的平方根,方差又定义为"平方均值减去均值的平方"为您的收藏。 SOOOO ...
total_squares = sum(number*number * count for number, count in counter)
mean_of_squares = total_squares / count
variance = mean_of_squares - mean * mean
std_dev = math.sqrt(variance)
稍微多一些手动工作,但如果数字集有很多重复,也应该快得多。
答案 2 :(得分:0)
除非您想编写自己的统计函数,否则没有prêt-à-porter解决方案(据我所知)。
所以最后你需要创建列表,最快的方法是使用numpy。一种方法是:
import numpy as np
# One memory allocation will be considerably faster
# if you have multiple discrete values.
elements = np.ones(48+49)
elements[0:48] *= 4082
elements[48:] *= 1146
# Then you can use numpy statistical functions to calculate
np.mean(elements)
np.std(elements)
# ...
更新:从现有collections.Counter()对象创建元素
c = collections.Counter({48: 4082, 49: 1146})
elements = np.ones(sum(c.values()))
idx = 0
for value, occurrences in c.iteritems():
elements[idx:idx + occurrences] *= value
idx += occurrences