2017-01-12 127 views
1

我有從哪個列表中得到非零值的平均值。計算非零值的平均值

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) 

我怎樣才能做到這一點的操作更有效率?

+2

非零值意味着'V = 0'。在你的情況下,'v> 0'意味着正數 –

+0

你不把輸入作爲列表的列表,如:[[[2,2,0,0,0],[1,1,0。 ...]]'或者它是一個數組? – Divakar

回答

2

如果你以一個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 
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 

對於小的投入,但是,你目前的做法可能是罰款。 然而值得注意的是,你現在的答案並不是實際採用所有非零元素,而只是積極因素。

+0

嘿,我只使用正數。但是,感謝這面旗幟,我沒有注意到它。 –

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])