【问题标题】:Calculate mean on values in python collections.Counter计算python collections.Counter中值的平均值
【发布时间】:2016-02-15 04:20:30
【问题描述】:

我正在分析一些非常紧密地聚集在一起的数字时间测量值。我想获得平均值、标准差等。有些输入很大,所以我想我可以避免创建数百万个数字的列表,而是 使用 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 对象中的值计算描述性统计数据,就像我有一个数字列表一样?我必须创建完整列表还是有快捷方式?

【问题讨论】:

  • (我自己没时间写答案,但是np.average 有一个权重参数,你可以手动做stddev,见here——如果有人想用这种方法我会删除它)

标签: python numpy


【解决方案1】:

collections.Counter()dict 的子类。只需使用Counter().values()获取计数列表,您可以使用标准库staticstics.mean() function

import statistics

counts = Counter(some_iterable_to_be_counted)
mean = statistics.mean(counts.values())

请注意,我在此处没有调用Counter.most_common(),这将生成您在问题中发布的(key, count) 元组列表。

如果您必须使用Counter.most_common() 的输出,您可以使用生成器表达式过滤掉计数:

mean = statistics.mean(count for key, count in most_common_list)

如果您要计算按其计数加权的平均 键值,您可以直接根据计数器值进行自己的计算:

mean = sum(key * count for key, count in counter.items()) / counter.total())

注意:我在那里使用了Counter.total(),这是 Python 3.10 中的新功能。在旧版本中。使用sum(counter.values())

对于中位数,使用statistics.median()

import statistics

counts = Counter(some_iterable_to_be_counted)
median = statistics.median(counts.values())

或者,对于key * value

median = statistics.median(key * count for key, count in counts.items())

【讨论】:

    【解决方案2】:

    虽然您可以在创建值列表后将所有内容卸载到 numpy,但这会比需要的速度慢。相反,您可以使用您需要的实际定义。

    平均值只是所有数字的总和除以它们的计数,所以很简单:

    sum_of_numbers = sum(number*count for number, count in counter.items())
    count = sum(count for n, count in counter.items())
    mean = sum_of_numbers / count
    

    标准差有点复杂。它是方差的平方根,而方差又被定义为您的收藏的“平方均值减去均值的平方”。呜呜呜……

    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)
    

    需要更多的手动操作,但如果数字集有很多重复,也应该会更快。

    【讨论】:

    • 为简洁起见喜欢这个。感谢@Martijn Pieters 澄清了 Python 的整数和浮点数学特性,请不要因为我接受这个答案而生气:)
    • 你仍然可以使用 numpy,它可能会更快:array = np.array(list(C.items())); mean = np.sum( array[:, 0] * array[:, 1]) / np.sum(array[:, 1])
    【解决方案3】:

    除非您想编写自己的统计函数,否则没有 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
    

    【讨论】:

    • 不,不需要创建列表。请查看其他答案。
    猜你喜欢
    • 2011-12-04
    • 1970-01-01
    • 1970-01-01
    • 2017-02-06
    • 2012-06-19
    • 2020-06-10
    • 1970-01-01
    相关资源
    最近更新 更多