python:可变长度2矩阵的平均值

python:可变长度2矩阵的平均值,python,arrays,numpy,Python,Arrays,Numpy,考虑以下可变长度2D数组 [ [1, 2, 3], [4, 5], [6, 7, 8, 9] ] 如何找到列中变量的平均值 我想要像[(1+4+6)/3,(2+5+7)/3,(3+8)/2,9/1] 因此最终结果将是[3.667,4.667,5.5,9] 使用numpy可以实现这一点吗 我尝试了np.mean(x,axis=0),但numpy希望数组的维数相同 现在,我正在弹出每列的元素并找到平均值。有没有更好的方法来达到效果?您可以使用熊猫: import pandas as

考虑以下可变长度2D数组

[
[1, 2, 3],
[4, 5],
[6, 7, 8, 9]
]       
如何找到列中变量的平均值

我想要像
[(1+4+6)/3,(2+5+7)/3,(3+8)/2,9/1]

因此最终结果将是
[3.667,4.667,5.5,9]

使用numpy可以实现这一点吗

我尝试了
np.mean(x,axis=0)
,但numpy希望数组的维数相同

现在,我正在弹出每列的元素并找到平均值。有没有更好的方法来达到效果?

您可以使用熊猫:

import pandas as pd

a = [[1, 2, 3],
     [4, 5],
     [6, 7, 8, 9]]

df = pd.DataFrame(a)
# 0  1   2   3
# 0  1  2   3 NaN
# 1  4  5 NaN NaN
# 2  6  7   8   9

df.mean()
# 0    3.666667
# 1    4.666667
# 2    5.500000
# 3    9.000000
# dtype: float64
下面是另一个仅使用numpy的解决方案:

import numpy as np
nrows = len(a)
ncols = max(len(row) for row in a)
arr = np.zeros((nrows, ncols))
arr.fill(np.nan)
for jrow, row in enumerate(a):
    for jcol, col in enumerate(row):
        arr[jrow, jcol] = col
print np.nanmean(arr, axis=0)
# array([ 3.66666667,  4.66666667,  5.5       ,  9.        ])

如果您想手动执行,我将执行以下操作:

max_length = 0
计算最大数组长度:

for array in arrays:
    if len(array) > max:
        max = len(array)
'None'

for array in arrays:
    while len(array) < max:
        array.append(None)
列==[(1,4,6),(2,5,7),(3,'None',8),('None','None',9)]

计算任何列表的平均值:

for col in columns:
    count = 0
    sum = 0.0
    for num in col:
        if num is not None:
            count += 1
            sum += float(num)
    print "%s: Avg %s" % (col, sum/count)
或作为填充数组后的列表理解:

[sum(filter(None, col))/float(len(filter(None, col))) for col in zip(*arrays)]
输出:

(1, 4, 6): Avg 3.66666666667
(2, 5, 7): Avg 4.66666666667
(3, 'None', 8): Avg 5.5
('None', 'None', 9): Avg 9.0

本文中列出了一种使用NumPy的几乎矢量化的方法。我们将尝试根据列表元素中的每个元素的位置为它们分配一个ID。然后可以将这些ID馈送到,因为它将执行基于ID的求和。最后,我们将总和分别除以每个ID的长度,得到最终的平均值

因此,我们将有一个这样的实现-

def variable_mean(a):
    vals = np.concatenate(a)
    lens = np.array(map(len,a))
    id_arr = np.ones(vals.size,dtype=int)
    id_arr[0] = 0
    id_arr[lens.cumsum()[:-1]] = -lens[:-1] + 1
    IDs = id_arr.cumsum()
    return np.bincount(IDs,vals)/np.bincount(IDs)
运行时测试-

In [298]: # Setup input 
     ...: N = 1000 # number of elems in input list
     ...: minL = 3 # min len of an element (list) in input list
     ...: maxL = 10 # max len of an element (list) in input list
     ...: a = [list(np.random.randint(0,9,(i))) \
     ...:       for i in np.random.randint(minL,maxL,(N))]
     ...: 

In [299]: %timeit pd.DataFrame(a).mean() #@Julien Spronck's pandas soln
100 loops, best of 3: 3.33 ms per loop

In [300]: %timeit variable_mean(a)
100 loops, best of 3: 2.36 ms per loop

In [301]: # Setup input 
     ...: N = 1000 # number of elems in input list
     ...: minL = 3 # min len of an element (list) in input list
     ...: maxL = 100 # max len of an element (list) in input list
     ...: a = [list(np.random.randint(0,9,(i))) \
     ...:       for i in np.random.randint(minL,maxL,(N))]
     ...: 

In [302]: %timeit pd.DataFrame(a).mean() #@Julien Spronck's pandas soln
10 loops, best of 3: 27.1 ms per loop

In [303]: %timeit variable_mean(a)
100 loops, best of 3: 9.58 ms per loop

使用as的非常简单的替代方法:

其中
my_list
等于:

[
[1, 2, 3],
[4, 5],
[6, 7, 8, 9]
] 

在Py3中,
zip\u longest
采用
fillvalue
参数:

In [1208]: ll=[
      ...: [1, 2, 3],
      ...: [4, 5],
      ...: [6, 7, 8, 9]
      ...: ]   
In [1209]: list(itertools.zip_longest(*ll, fillvalue=np.nan))
Out[1209]: [(1, 4, 6), (2, 5, 7), (3, nan, 8), (nan, nan, 9)]
通过填写
nan
,我可以使用
np.nanmean
来取忽略
nan
的平均值
nanmean
将其输入(此处为前一行的
)转换为数组:

In [1210]: np.nanmean(_, axis=1)
Out[1210]: array([ 3.66666667,  4.66666667,  5.5       ,  9.        ])

使用0作为填充值会破坏平均值。@TemporalWolf Ohh是的。更新了答案,该答案应称为Numpythonic;-)@哈哈,这就是我主要做的;)
In [1208]: ll=[
      ...: [1, 2, 3],
      ...: [4, 5],
      ...: [6, 7, 8, 9]
      ...: ]   
In [1209]: list(itertools.zip_longest(*ll, fillvalue=np.nan))
Out[1209]: [(1, 4, 6), (2, 5, 7), (3, nan, 8), (nan, nan, 9)]
In [1210]: np.nanmean(_, axis=1)
Out[1210]: array([ 3.66666667,  4.66666667,  5.5       ,  9.        ])