我想用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
分别)?
答案 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
广播解决方案的运行时似乎不依赖于数组大小。