合并两个 numpy 掩码数组的有效方法
Efficient way of merging two numpy masked arrays
我有两个要合并的 numpy 掩码数组。我正在使用以下代码:
import numpy as np
a = np.zeros((10000, 10000), dtype=np.int16)
a[:5000, :5000] = 1
am = np.ma.masked_equal(a, 0)
b = np.zeros((10000, 10000), dtype=np.int16)
b[2500:7500, 2500:7500] = 2
bm = np.ma.masked_equal(b, 0)
arr = np.ma.array(np.dstack((am, bm)), mask=np.dstack((am.mask, bm.mask)))
arr = np.prod(arr, axis=2)
plt.imshow(arr)
问题是 np.prod()
操作很慢(在我的电脑上是 4 秒)。有没有其他方法可以更有效地获取合并数组?
不要使用 dstack()
和 prod()
的最后两行,试试这个:
arr = np.ma.array(am.filled(1) * bm.filled(1), mask=(am.mask * bm.mask))
现在您根本不需要 prod()
,并且完全避免分配 3D 数组。
受已接受答案的启发,我找到了一种合并屏蔽数组的简单方法。它可以对掩码进行一些逻辑运算并简单地添加 0 个填充数组。
import numpy as np
a = np.zeros((1000, 1000), dtype=np.int16)
a[:500, :500] = 2
am = np.ma.masked_equal(a, 0)
b = np.zeros((1000, 1000), dtype=np.int16)
b[250:750, 250:750] = 3
bm = np.ma.masked_equal(b, 0)
c = np.zeros((1000, 1000), dtype=np.int16)
c[500:1000, 500:1000] = 5
cm = np.ma.masked_equal(c, 0)
bm.mask = np.logical_or(np.logical_and(am.mask, bm.mask), np.logical_not(am.mask))
am = np.ma.array(am.filled(0) + bm.filled(0), mask=(am.mask * bm.mask))
cm.mask = np.logical_or(np.logical_and(am.mask, cm.mask), np.logical_not(am.mask))
am = np.ma.array(am.filled(0) + cm.filled(0), mask=(am.mask * cm.mask))
plt.imshow(am)
我希望有人能在某个时候发现这有帮助。蒙面数组似乎不是很有效。所以,如果有人找到合并数组的替代方法,我会很高兴知道。
更新:根据@morningsun 的评论,此实现速度提高了 30%,也更加简单:
import numpy as np
a = np.zeros((1000, 1000), dtype=np.int16)
a[:500, :500] = 2
am = np.ma.masked_equal(a, 0)
b = np.zeros((1000, 1000), dtype=np.int16)
b[250:750, 250:750] = 3
bm = np.ma.masked_equal(b, 0)
c = np.zeros((1000, 1000), dtype=np.int16)
c[500:1000, 500:1000] = 5
cm = np.ma.masked_equal(c, 0)
am[am.mask] = bm[am.mask]
am[am.mask] = cm[am.mask]
plt.imshow(am)
我采用了另一种可能不是特别有效但相当容易扩展和实施的方法。
(我知道我正在回答一个超过 3 年的问题,其功能在 numpy 中已经存在很长时间了,但请耐心等待)
numpy中的np.where
函数有两个主要目的(有点奇怪),第一个是给你一个布尔数组的索引:
>>> import numpy as np
>>> a = np.arange(12).reshape(3, 4)
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> m = (a % 3 == 0)
>>> m
array([[ True, False, False, True],
[False, False, True, False],
[False, True, False, False]], dtype=bool)
>>> row_ind, col_ind = np.where(m)
>>> row_ind
array([0, 0, 1, 2])
>>> col_ind
array([0, 3, 2, 1])
np.where
函数的另一个目的是根据给定的布尔数组是否为 True/False:
从两个数组中进行选择
>>> np.where(m, a, np.zeros(a.shape))
array([[ 0., 0., 0., 3.],
[ 0., 0., 6., 0.],
[ 0., 9., 0., 0.]])
事实证明,还有一个 numpy.ma.where
处理屏蔽数组...
给定相同形状的掩码数组列表,我的代码如下所示:
merged = masked_arrays[0]
for ma in masked_arrays[1:]:
merged = np.ma.where(ma.mask, merged, ma)
正如我所说,效率不是特别高,但实施起来肯定很容易。
HTH
我有两个要合并的 numpy 掩码数组。我正在使用以下代码:
import numpy as np
a = np.zeros((10000, 10000), dtype=np.int16)
a[:5000, :5000] = 1
am = np.ma.masked_equal(a, 0)
b = np.zeros((10000, 10000), dtype=np.int16)
b[2500:7500, 2500:7500] = 2
bm = np.ma.masked_equal(b, 0)
arr = np.ma.array(np.dstack((am, bm)), mask=np.dstack((am.mask, bm.mask)))
arr = np.prod(arr, axis=2)
plt.imshow(arr)
问题是 np.prod()
操作很慢(在我的电脑上是 4 秒)。有没有其他方法可以更有效地获取合并数组?
不要使用 dstack()
和 prod()
的最后两行,试试这个:
arr = np.ma.array(am.filled(1) * bm.filled(1), mask=(am.mask * bm.mask))
现在您根本不需要 prod()
,并且完全避免分配 3D 数组。
受已接受答案的启发,我找到了一种合并屏蔽数组的简单方法。它可以对掩码进行一些逻辑运算并简单地添加 0 个填充数组。
import numpy as np
a = np.zeros((1000, 1000), dtype=np.int16)
a[:500, :500] = 2
am = np.ma.masked_equal(a, 0)
b = np.zeros((1000, 1000), dtype=np.int16)
b[250:750, 250:750] = 3
bm = np.ma.masked_equal(b, 0)
c = np.zeros((1000, 1000), dtype=np.int16)
c[500:1000, 500:1000] = 5
cm = np.ma.masked_equal(c, 0)
bm.mask = np.logical_or(np.logical_and(am.mask, bm.mask), np.logical_not(am.mask))
am = np.ma.array(am.filled(0) + bm.filled(0), mask=(am.mask * bm.mask))
cm.mask = np.logical_or(np.logical_and(am.mask, cm.mask), np.logical_not(am.mask))
am = np.ma.array(am.filled(0) + cm.filled(0), mask=(am.mask * cm.mask))
plt.imshow(am)
我希望有人能在某个时候发现这有帮助。蒙面数组似乎不是很有效。所以,如果有人找到合并数组的替代方法,我会很高兴知道。
更新:根据@morningsun 的评论,此实现速度提高了 30%,也更加简单:
import numpy as np
a = np.zeros((1000, 1000), dtype=np.int16)
a[:500, :500] = 2
am = np.ma.masked_equal(a, 0)
b = np.zeros((1000, 1000), dtype=np.int16)
b[250:750, 250:750] = 3
bm = np.ma.masked_equal(b, 0)
c = np.zeros((1000, 1000), dtype=np.int16)
c[500:1000, 500:1000] = 5
cm = np.ma.masked_equal(c, 0)
am[am.mask] = bm[am.mask]
am[am.mask] = cm[am.mask]
plt.imshow(am)
我采用了另一种可能不是特别有效但相当容易扩展和实施的方法。
(我知道我正在回答一个超过 3 年的问题,其功能在 numpy 中已经存在很长时间了,但请耐心等待)
numpy中的np.where
函数有两个主要目的(有点奇怪),第一个是给你一个布尔数组的索引:
>>> import numpy as np
>>> a = np.arange(12).reshape(3, 4)
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> m = (a % 3 == 0)
>>> m
array([[ True, False, False, True],
[False, False, True, False],
[False, True, False, False]], dtype=bool)
>>> row_ind, col_ind = np.where(m)
>>> row_ind
array([0, 0, 1, 2])
>>> col_ind
array([0, 3, 2, 1])
np.where
函数的另一个目的是根据给定的布尔数组是否为 True/False:
>>> np.where(m, a, np.zeros(a.shape))
array([[ 0., 0., 0., 3.],
[ 0., 0., 6., 0.],
[ 0., 9., 0., 0.]])
事实证明,还有一个 numpy.ma.where
处理屏蔽数组...
给定相同形状的掩码数组列表,我的代码如下所示:
merged = masked_arrays[0]
for ma in masked_arrays[1:]:
merged = np.ma.where(ma.mask, merged, ma)
正如我所说,效率不是特别高,但实施起来肯定很容易。
HTH