扩展numpy mask

时间:2016-02-16 14:21:49

标签: python arrays numpy

我想用a掩盖一个numpy数组mask。面具与a具有完全相同的形状,但无论如何都可以屏蔽a(我猜是因为额外的维度是1维(广播?))。 / p>

a.shape
>>> (3, 9, 31, 2, 1)
mask.shape
>>> (3, 9, 31, 2)
masked_a = ma.masked_array(a, mask)

但是,相同的逻辑不适用于在其最后一维中有5个元素的数组b

ext_mask = mask[..., np.newaxis] # extending or not extending has same effect
ext_mask.shape
>>> (3, 9, 31, 2, 1)

b.shape
>>> (3, 9, 31, 2, 5)
masked_b = ma.masked_array(b, ext_mask)
>>> numpy.ma.core.MaskError: Mask and data not compatible: data size is 8370, mask size is 1674.

如何通过将(3, 9, 31, 2, 5)掩码的最后一个维度中的(3, 9, 31, 2)值展开为True,从(3, 9, 31, 2)掩码创建[True, True, True, True, True]掩码(和False分别)?

1 个答案:

答案 0 :(得分:3)

这给出了期望的结果:

masked_b = ma.masked_array(*np.broadcast(b, ext_mask))

我没有对此方法进行过分析,但它应该比分配新掩码更快。根据{{​​3}},不会复制任何数据:

  

这些数组是原始数组的视图。他们通常不是   连续的。此外,广播阵列的多个元素   可以指单个存储位置。如果你需要写信给   数组,先制作副本。

可以验证无复制行为:

bb, mb = np.broadcast(b, ext_mask)
print(mb.shape)       # (3, 9, 31, 2, 5) - same shape as b
print(mb.base.shape)  # (3, 9, 31, 2) - the shape of the original mask
print(mb.strides)     # (558, 62, 2, 1, 0) - that's how it works: 0 stride

numpy开发者如何实现广播,令人印象深刻。通过沿最后一个维度使用步长0来重复值。 Whow!

修改

我将广播和分配的速度与此代码进行了比较:

import numpy as np
from numpy import ma

a = np.random.randn(30, 90, 31, 2, 1)
b = np.random.randn(30, 90, 31, 2, 5)

mask = np.random.randn(30, 90, 31, 2) > 0
ext_mask = mask[..., np.newaxis]

def broadcasting(a=a, b=b, ext_mask=ext_mask):
    mb1 = ma.masked_array(*np.broadcast_arrays(b, ext_mask))

def allocating(a=a, b=b, ext_mask=ext_mask):
    m2 = np.empty(b.shape, dtype=bool)
    m2[:] = ext_mask
    mb2 = ma.masked_array(b, m2)

广播显然比分配更快,在这里:

    # array size: (30, 90, 31, 2, 5)

In [23]: %timeit broadcasting()
The slowest run took 10.39 times longer than the fastest. This could mean that an intermediate result is being cached.
10000 loops, best of 3: 39.4 µs per loop

In [24]: %timeit allocating()
The slowest run took 4.86 times longer than the fastest. This could mean that an intermediate result is being cached.
1000 loops, best of 3: 982 µs per loop

请注意,为了显示速度差异,我必须增加数组大小。使用原始数组维度分配比广播稍快:

    # array size: (3, 9, 31, 2, 5)

In [28]: %timeit broadcasting()
The slowest run took 9.36 times longer than the fastest. This could mean that an intermediate result is being cached.
10000 loops, best of 3: 39 µs per loop

In [29]: %timeit allocating()
The slowest run took 9.22 times longer than the fastest. This could mean that an intermediate result is being cached.
10000 loops, best of 3: 32.6 µs per loop

广播解决方案的运行时似乎不依赖于数组大小。