这感觉有点粗糙和凌乱,但它确实没有循环。在
主要有两项任务:展开data以便可以用masks-从(5,4)到(5,3,4)索引
将means应用于行组;我能找到的最接近的是np.sum.reduceat。在
构造reduceat索引:In [253]: cnt = masks.sum(axis=1)
In [254]: cnt1=np.concatenate(([0],np.cumsum(cnt)[:-1]))
In [255]: cnt
Out[255]: array([2, 1, 2, 1, 2]) # True count per row
In [256]: cnt1
Out[256]: array([0, 2, 3, 5, 6]) # reduceat index positions
展开data和{}:
^{pr2}$
add行并除以每个组的行数In [258]: np.add.reduceat(mdata,cnt1,0)/cnt[:,None]
Out[258]:
array([[ 2., 3., 4., 5.],
[ 4., 5., 6., 7.],
[ 6., 7., 8., 9.],
[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.]])
万一有帮助:In [263]: mdata
Out[263]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 4, 5, 6, 7],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[ 0, 1, 2, 3],
[ 0, 1, 2, 3],
[ 8, 9, 10, 11]])
可能更好的方法是In [285]: data[np.where(masks)[1],:]
Out[285]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 4, 5, 6, 7],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[ 0, 1, 2, 3],
[ 0, 1, 2, 3],
[ 8, 9, 10, 11]])
where(...)[1]是True在masks中的列位置,这是我们要从data中选择的行。在
============================
@capitalistcuttle也创建一个(5,3,4)数组,但通过将False行归零,从而避免了对reduceat的需要。这样就可以进入mean或sum而不影响值。这让我想起了掩码数组是如何执行这样的任务的。它们fill使用不影响计算的0或1这样的值屏蔽值。在
受此启发,这里有一个MaskedArray解决方案
将data和{}都展开为(5,3,4)大小:In [322]: data1=data[None,:,:].repeat(5,0)
In [323]: masks1=masks[:,:,None].repeat(4,-1)
In [324]: data1.shape, masks1.shape
Out[324]: ((5, 3, 4), (5, 3, 4))
从中生成蒙版数组:In [325]: madata=np.ma.MaskedArray(data1,~masks1)
In [326]: madata
Out[326]:
masked_array(data =
[[[0 1 2 3]
[4 5 6 7]
[ ]]
[[ ]
[4 5 6 7]
[ ]]
...
[[0 1 2 3]
[ ]
[8 9 10 11]]],
mask =
[[[False False False False]
[False False False False]
[ True True True True]]
[[ True True True True]
[False False False False]
[ True True True True]]
...],
fill_value = 999999)
现在我们可以简单地使用mean方法,让它处理0填充并调整有效行的数量。在In [327]: madata.mean(axis=1)
Out[327]:
masked_array(data =
[[2.0 3.0 4.0 5.0]
[4.0 5.0 6.0 7.0]
[6.0 7.0 8.0 9.0]
[0.0 1.0 2.0 3.0]
[4.0 5.0 6.0 7.0]],
mask =
[[False False False False]
[False False False False]
[False False False False]
[False False False False]
[False False False False]],
fill_value = 1e+20)
将.data属性转换回正则数组。在
这种MaskedArray方法可能比较慢,因为它创建了一个更大的数组,但它可能更通用——它可以用于操作,只要它们是在np.ma或其方法中定义的。在