计算非零值的平均值

时间:2017-01-12 00:43:55

标签: python list numpy optimization

我列出了我的非零值的平均值。

E.G

 [2,2,0,0,0] -> 2    
 [1,1,0,1,0]  -> 1  
 [0,0,0,9,0] -> 9    
 [2,3,0,0,0] -> 2.5

目前我正在这样做:

list_ = [1,1,0,1,0]  
non_zero = [float(v) for v in list_ if v>0]
averge = sum(non_zero)/len(non_zero)

如何更有效地执行此操作?

3 个答案:

答案 0 :(得分:3)

如果你从一个numpy数组开始,你可以使用np.nonzero来过滤数组,然后取平均值:

a = np.array([2,3,0,0,0])
average = a[np.nonzero(a)].mean()

您还可以通过布尔索引进行过滤,这似乎更快:

average = a[a!=0].mean()

您还可以使用a>0轻松更改上述方法以过滤正值。

<强>计时

使用以下设置:

a = np.random.randint(100, size=10**6)

我得到以下时间:

%timeit a[a!=0].mean()
100 loops, best of 3: 4.59 ms per loop

%timeit a[a.nonzero()].mean()
100 loops, best of 3: 9.82 ms per loop

答案 1 :(得分:3)

这是一种矢量化方法,在将列表列表转换为2D数组后进行求和 -

from __future__ import division
a = np.asarray(list_)
a.sum(1)/(a!=0).sum(1)

示例运行 -

In [32]: list_  #  Input list of lists
Out[32]: [[2, 2, 0, 0, 0], [1, 1, 0, 1, 0], [0, 0, 0, 9, 0], [2, 3, 0, 0, 0]]

In [33]: a = np.asarray(list_) # Convert to array

In [34]: a.sum(1)/(a!=0).sum(1) # Divide row sums by count of non-zeros 
Out[34]: array([ 2. ,  1. ,  9. ,  2.5])

答案 2 :(得分:2)

您可以使用np.nonzero

l = np.array([2,2,0,0,0])

l[l.nonzero()].mean()
Out[17]: 2.0

一个粗略的基准,包含您当前的方法和这个方法:

def luis_way(l):
    non_zero = [float(v) for v in l if v>0]
    average = sum(non_zero)/len(non_zero)
    return average

def np_way(l):
    return l[l.nonzero()].mean()



In [19]: some_l = np.random.randint(2, size=10000)
In [20]: %timeit luis_way(some_l)
100 loops, best of 3: 4.72 ms per loop
In [21]: %timeit np_way(some_l)
1000 loops, best of 3: 262 µs per loop

对于小型输入,您当前的方法可能很好。 然而值得注意的是,您当前的答案实际上并未采用所有非零元素,而只采用正元素。