假设我有以下列表列表:
a = [
[1, 2, 3],
[2, 3, 4],
[3, 4, 5, 6]
]
我想得到数组中每个第n个元素的平均值.但是,当想要以简单的方式执行此操作时,由于长度不同,Python会生成越界错误.我通过给每个数组赋予最长数组的长度,并用None填充缺失值来解决这个问题.
不幸的是,这样做使得无法计算平均值,因此我将数组转换为掩码数组.下面显示的代码有效,但看起来相当麻烦.
import numpy as np
import numpy.ma as ma
a = [ [1, 2, 3],
[2, 3, 4],
[3, 4, 5, 6] ]
# Determine the length of the longest list
lenlist = []
for i in a:
lenlist.append(len(i))
max = np.amax(lenlist)
# Fill each list up with None's until required length is reached
for i in a:
if len(i) <= max:
for j in range(max - len(i)):
i.append(None)
# Fill temp_array up with the n-th element
# and add it to temp_array
temp_list = []
masked_arrays = []
for j in range(max):
for i in range(len(a)):
temp_list.append(a[i][j])
masked_arrays.append(ma.masked_values(temp_list, None))
del temp_list[:]
# Compute the average of each array
avg_array = []
for i in masked_arrays:
avg_array.append(np.ma.average(i))
print avg_array
有没有办法更快地完成这项工作?列表的最终列表将包含600000’行’和最多100’列’,因此效率非常重要:-).
解决方法:
tertools.izip_longest会为你做所有的填充,所以你的代码可以简化为:
import numpy as np
import numpy.ma as ma
from itertools import izip_longest
a = [ [1, 2, 3],
[2, 3, 4],
[3, 4, 5, 6] ]
averages = [np.ma.average(ma.masked_values(temp_list, None)) for temp_list in izip_longest(*a)]
print(averages)
[2.0, 3.0, 4.0, 6.0]
不知道关于numpy逻辑的最快方法是什么,但这肯定比你自己的代码更有效率.
如果你想要一个更快的纯python解决方案:
from itertools import izip_longest, imap
a = [[1, 2, 3],
[2, 3, 4],
[3, 4, 5, 6]]
def avg(x):
x = filter(None, x)
return sum(x, 0.0) / len(x)
filt = imap(avg, izip_longest(*a))
print(list(filt))
[2.0, 3.0, 4.0, 6.0]
如果数组中的0不能正常工作,则0将被视为Falsey,在这种情况下你必须使用list comp进行过滤,但它仍然会更快:
def avg(x):
x = [i for i in x if i is not None]
return sum(x, 0.0) / len(x)
filt = imap(avg, izip_longest(*a))
标签:python,arrays,nan,numpy,list