我在python中有一个特定的任务要执行。效率和速度是这里最重要的,这就是为什么我张贴这个问题。
我需要获得列表中项目的平均值,但只需要获得至少是列表模式发生的一半的项目的平均值。
例如,如果列表是[1,2,2,3,4,4,4,4],我需要得到2,2,4,4,4,4的平均值。由于4是列表的模式,并且发生了四次,所以唯一至少发生了四次(两次)的元素是2。因此,我对所有出现的1和3进行了折扣,并对列表进行了平均处理。
我不知道最有效的方法是什么。我知道如何强行计算解决方案,但这显然不是最快的实现。
我认为最好使用numpy数组,但是由于我会经常添加到列表中,所以我认为这不是最好的选择。
我的其他想法是可能使用来自collections模块的基于collections的方法。但再次,我不知道这是最快或最明智的执行这样一个相当奇怪的计算。
发布于 2016-09-24 23:19:03
要获得列表的模式,必须至少遍历整个列表一次(从技术上讲,只要其中一个元素的计数超过列表中的其余项,就可以立即停止,但效率是可以忽略不计的)。
Python有一种高效而简单的方法来使用Counter来实现这一点。
from __future__ import division
from collections import Counter
from itertools import islice
data = [1,2,2,3,4,4,4,4]
c = Counter(data)
# Get the mode
mode, mode_n = c.most_common(1)[0]
# Store the cumulative sum and count so we can compute the mean
# Process the most common element (the mode) first since we
# already have that data.
cumulative_sum = mode * mode_n
cumulative_n = mode_n
# Process the remaining elements. most_common returns the remaining
# elements and their counts in descending order by the number of times
# the appear in the original list. We can skip the first element since
# we've already processed it. As soon as an element is less numerous
# than half the mode, we can stop processing further elements.
for val, val_n in islice(c.most_common(), 1, None):
if val_n < mode_n / 2:
break
cumulative_sum += val * val_n
cumulative_n += val_n
# Compute the Mean
avg = cumulative_sum / cumulative_n我唯一不确定的是你是如何对待出现奇数的模式的。如果模式出现5时间,则在检查其他元素时,您是聚集到3还是向下转到2?
目前,它正在四舍五入,但是如果您想将其舍入,只需将其更改为:
if val_n < mode_n // 2:发布于 2016-09-25 02:53:33
如果您决定使用numpy,下面是使用numpy.unique和numpy.average的简明方法
In [54]: x = np.array([1, 2, 2, 3, 4, 4, 4, 4])
In [55]: uniqx, counts = np.unique(x, return_counts=True)
In [56]: keep = counts >= 0.5*counts.max()
In [57]: np.average(uniqx[keep], weights=counts[keep])
Out[57]: 3.3333333333333335请注意,np.unique对其参数进行了排序,因此其时间复杂度为O(n*log(n)),而这个问题可以用O(n)的算法来解决。使用具有典型长度的数组进行定时比较,然后根据其渐近时间复杂性排除这种方法。
https://stackoverflow.com/questions/39681725
复制相似问题