2017-04-17 96 views
0

我不確定我的標題是否與我正在嘗試做的完全一致,但本質上我得到了列表的平均值,並且我希望它不會添加到列表中,而是添加到列表中:顛倒python中的循環?

listoflists = [[1,2,3], [1,0,4], [0,5,1]] 
#want [1, 3.5, 2.67] 
final = [] 
for i in range(len(listoflists)): 
    count = 0 
    val = 0 
    for j in range(len(listoflists[i])): 
     if listoflists[i][j] != 0: 
      count += 1 
      val += listoflists[i][j] 
    final.append(float(val)/count) 
print final #currently returns [2.0, 2.5, 3.0] 

而不是添加1,2,3,並得到平均值6/3 = 2,我想它添加1,1,0(每個列表中的第一個值)並獲得2/2 = 1(如果0 ,不要把它計算在內) 我該如何讓循環來做到這一點呢?

+2

使用[zip()](https://docs.python.org/3/library/functions.html#zip)轉置列表列表,然後使用[sum()](https:// docs。 python.org/3/library/functions.html#sum)來獲取轉置列表的總和。 – wwii

回答

0

你可以先轉換列表中,用拉鍊

zip(*listoflists) 
>>> [(1, 1, 0), (2, 0, 5), (3, 4, 1)] 

這裏有一個辦法做到這一點:

final = [] 
for l in zip(*listoflists): 
    final.append(float(sum(l))/len([x for x in l if x != 0])) 
print final 
0

你可以使用NumPy的。

arr = np.array(listoflists) 
sums = arr.sum(axis=0) 
final = []  
for i in range(arr.shape[1]): 
    final.append(sums[i]/np.count_nonzero(arr[:,i]) 

或者更好的是完全避免循環。

arr = np.array(listoflists) 
sums = arr.sum(0) 
non_zeros = (arr != 0).sum(0) 
final = sums/zon_zeros 
0

這會爲你工作:

listoflists = [[1,2,3], [1,0,4], [0,5,1]] 
second_list = zip(*listoflists) 
new_list = map(list, second_list) 

final_list = [] 
without_zero = [] 
for i in new_list: 
    for b in i: 
     if b != 0: 
      without_zero.append(b) 
    final_list.append(without_zero) 
    without_zero = [] 

average = [sum(i)/float(len(i)) for i in final_list] 

print average 

編輯: 只使用列表理解和zip另一種方式:

listoflists = [[1,2,3], [1,0,4], [0,5,1]] 
new_list = zip(*listoflists) 
result = [sum([i for i in b if i != 0])/float(len([i for i in b if i != 0])) for b in new_list] 
print result 
0
from __future__ import division 
map(lambda *column: sum(column)/sum(x>0 for x in column), *listoflists) 

另一種可能性(Python的3只):

from statistics import mean 
[mean(filter(None, column)) for column in zip(*listoflists)] 

替代numpy的實現(適用於Python的2以及):

import numpy as np 
a = np.array(listoflists) 
np.average(a, axis=0, weights=a>0) 
0

讓改革你的代碼是多一點的Python等。在Python中,我們可以迭代(遍歷列表)並直接獲取對象,我們並不需要使用索引。

final = [] 
for i in listoflists: 
    count = 0 
    val = 0 

    for j in i: 
     if j != 0: 
      count += 1 
      val += j 
    final.append(float(val)/count) 

print final 

此代碼是完全相同的和你沒有索引,j的是,我們所得到的實際子項(數字)。


做你想做什麼,Python有一個方便的zip()功能,調換子列表。例如,如果我們有以下列表[1,2] , [3,4]當我們zip([1,2],[3,4])這些列表,我們得到[(1, 3), (2, 4)]

我們可以利用這個使用*符號列表清單之前拆包列表做你想要什麼,並zip()支持這一點。回到我們之前的例子,我們可以列出一個列表x = [[1,2],[3,4]],並將x和*一起傳遞給zip以獲得我們想要的。我們將會得到[(1, 3), (2, 4)]。將這些與你所擁有的結合在一起會給你想要的結果。

final = [] 
for i in zip(*listoflists): 
    count = 0 
    val = 0 

    for j in i: 
     if j != 0: 
      count += 1 
      val += j 
    final.append(float(val)/count) 

我們可以更通過提高這些建在從諸如sum()這將總結所有的項目列表中,如果可能,你已經知道len()可與filter()使用過濾掉0。從文檔:

(項目在iterable如果項目)如果函數是無。

因此,我們檢查,如果該列表中包含項目的是價值,而0是失敗時if 0:

final = [] 
for i in zip(*listoflists): 
    if i: 
     final.append(float(sum(i))/len(filter(None, i))) 
print final 

我們可以走一步和壓縮功能,通過使用一個Python提供的最新東西,list comprehensions

print [float(sum(i))/len(filter(None,i)) for i in zip(*listoflists)] 

注意一些這些答案可能並不像其他人那樣優化,但我的答案集中在不同的方式,只有內置插件才能做到。