Python 从非常大的列表中排除特定值的平均值

Python 从非常大的列表中排除特定值的平均值,python,python-3.x,statistics,mean,Python,Python 3.x,Statistics,Mean,我正在处理一个非常大的旅行时间列表(~1GB),并试图对其进行平均,但有一个怪癖,即如果旅行不可能,则将该值设置为可能的最高整数值,这会破坏整个计算。旅行时间存储在列表中,列表存储在字典中 从A点到B点,从B点到C点的情况如下: {'AB':[3,5,10],'BC':[2,3,5,10,2147483647]} AB之间的平均值应为6,BC之间的平均值应为5(而不是429496733.4) 如何从平均计算中排除恶意值?该模块提供了一个函数,可以将迭代器作为输入,因此您不必复制列表来过滤掉要丢

我正在处理一个非常大的旅行时间列表(~1GB),并试图对其进行平均,但有一个怪癖,即如果旅行不可能,则将该值设置为可能的最高整数值,这会破坏整个计算。旅行时间存储在列表中,列表存储在字典中

从A点到B点,从B点到C点的情况如下:

{'AB':[3,5,10],'BC':[2,3,5,10,2147483647]}
AB之间的平均值应为6,BC之间的平均值应为5(而不是429496733.4)

如何从平均计算中排除恶意值?

该模块提供了一个函数,可以将迭代器作为输入,因此您不必复制列表来过滤掉要丢弃的值

下面是一个模拟的数据示例,其中100万个元素中有90%在1到9之间(含1到9),10%是您的rogue值:

from random import randint, random

data = [randint(1, 9) if random() < 0.9 else 2147483647 for _ in range(1000000)]
…下面是如何在它上迭代排除流氓值:

>>> from statistics import mean

>>> mean(data)
215405499.193486
>>> mean(x for x in data if x != 2147483647)
4.998926301609214
在字典中总结:

>>> travel_times = {'AB':[3,5,10],'BC':[2,3,5,10,2147483647]}
>>> {k: mean(x for x in v if x != 2147483647) for k, v in travel_times.items()}
{'BC': 5, 'AB': 6}

根据上面用户707650的评论,这里有一个解决方案,它利用
numpy
并在计算平均值之前将每个列表转换为屏蔽数组:

>>> import numpy as np

>>> travel_times = {'AB':[3,5,10],'BC':[2,3,5,10,2147483647]}

>>> {k: np.nanmean(np.ma.MaskedArray(v, mask=(np.array(v) == 2147483647))) 
   for k, v in travel_times.items()}

{'AB': 6.0, 'BC': 5.0}
使用@zero piraeus答案中的大型列表示例,我们可以看到执行时间的差异:

from random import randint, random
from statistics import mean
import numpy as np

data = [randint(1, 9) if random() < 0.9 else 2147483647 for _ in range(1000000)]

对于大列表,考虑使用NUMPY数组。您可以将其转换为屏蔽数组,屏蔽超过限制的值,然后使用
np.nanmean
。或者,计算中值而不是平均值(带或不带numpy,带或不带遮罩值)。
>>> %timeit mean(x for x in data if x != 2147483647)
1 loop, best of 3: 531 ms per loop

>>> %timeit np.nanmean(np.ma.MaskedArray(data, mask=(np.array(data) == 2147483647)))
10 loops, best of 3: 160 ms per loop