这将得到所需的结果:
masked_b = ma.masked_array(*np.broadcast(b, ext_mask))
我没有对这种方法进行过分析,但它应该比分配一个新的掩码更快。根据
文档,不会复制任何数据:
这些数组是原始数组的视图。它们通常不是连续的。此外,广播数组的一个以上元素可能指向单个内存位置。如果需要向数组写入内容,请先进行复制。
可以验证没有复制行为:
bb, mb = np.broadcast(b, ext_mask)
print(mb.shape)
print(mb.base.shape)
print(mb.strides)
很惊人的是numpy开发者如何实现广播。通过在最后一个维度上使用步幅为0来重复值。哇!
编辑
我使用以下代码比较了广播和分配的速度:
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
广播解决方案的运行时似乎不取决于数组大小。
masked_b = ma.masked_array(*np.broadcast(b, ext_mask))
,但我不知道为什么ma.masked_array
没有自动广播。编辑:也许是因为它只想为了效率而存储两个大小相等的数组的视图? - MB-FTypeError: __new__() 最多接受 11 个参数(已提供 8371 个)
。 - orangebroadcast_arrays
返回到原始数组的视图,这意味着不会执行任何分配。 - MB-F