有效计算均值和中位数

Calculate mean and median efficiently

按顺序查找 Python 列表中行的均值和中值的最有效方法是什么?

比如我的列表:

input_list = [1,2,4,6,7,8]

我想生成一个包含以下内容的输出列表:

output_list_mean = [1,1.5,2.3,3.25,4,4.7]
output_list_median = [1,1.5,2.0,3.0,4.0,5.0]

其中均值计算如下:

中位数计算如下:

我试过用下面的循环来实现它,但是看起来效率很低。

import numpy

input_list = [1,2,4,6,7,8]

for item in range(1,len(input_list)+1):
    print(numpy.mean(input_list[:item]))
    print(numpy.median(input_list[:item]))

您可以使用 itertools.islice 对数组进行切片并使用 np.fromiternp.mean :

>>> arr=np.array([1,2,4,6,7,8])
>>> l=arr.size
>>> from itertools import islice
>>> [np.fromiter(islice(arr,0,i+1),float).mean(dtype=np.float32) for i in xrange(l)]
[1.0, 1.5, 2.3333333, 3.25, 4.0, 4.6666665]

作为替代答案,如果你想要平均值,你可以使用 np.cumsum 来获得你的元素的累加和,并使用 np.true_divide 与主数组相除:

>>> np.true_divide(np.cumsum(arr),arr)
array([ 1. ,  1.5,  2. ,  2.5,  3. ,  3.5,  4. ,  4.5])

您自己做的任何事情,尤其是中位数,要么需要大量工作,要么效率非常低,但是 Pandas 内置了您所追求的功能的高效实现,扩展均值是 O(n),扩展中位数是 O(n*log(n)) 使用跳跃列表:

import pandas as pd
import numpy as np

input_list = [1, 2, 4, 6, 7, 8]

>>> pd.expanding_mean(np.array(input_list))
array([ 1.     ,  1.5    ,  2.33333,  3.25   ,  4.     ,  4.66667])

>>> pd.expanding_median(np.array(input_list))
array([ 1. ,  1.5,  2. ,  3. ,  4. ,  5. ])
import numpy as np
a = np.array([1,2,4,6,7,8])

使用 numpy.meshgrid(还有其他有效的公式)和 numpy.triu 创建一个包含您感兴趣的值的数组。

x, y = np.meshgrid(a,a)
# y = a.repeat(len(a)).reshape(len(a), len(a))
c = np.triu(y)

>>> y
array([[1, 1, 1, 1, 1, 1],
       [2, 2, 2, 2, 2, 2],
       [4, 4, 4, 4, 4, 4],
       [6, 6, 6, 6, 6, 6],
       [7, 7, 7, 7, 7, 7],
       [8, 8, 8, 8, 8, 8]])
>>> c
array([[1, 1, 1, 1, 1, 1],
       [0, 2, 2, 2, 2, 2],
       [0, 0, 4, 4, 4, 4],
       [0, 0, 0, 6, 6, 6],
       [0, 0, 0, 0, 7, 7],
       [0, 0, 0, 0, 0, 8]])

定义一个函数 returns 所有非零值的中位数并将其应用于您的 有趣 数组。

def foo(a):
    '''return the the median of the non-zero elements of a 1d array
    '''
    return np.median(a[a.nonzero()])
d = np.apply_along_axis(foo, 0, c)

>>> d
array([ 1. ,  1.5,  2. ,  3. ,  4. ,  5. ])
>>>