2017-04-17 101 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)] 

注意一些这些答案可能并不像其他人那样优化,但我的答案集中在不同的方式,只有内置插件才能做到。