NumPy 数组索引和替换
NumPy Array Indexing and Replacing
我有一个 3d numpy 数组如下:
(3L, 5L, 5L)
如果一个元素在 3d 位置,例如 [150, 160, 170]
存在。如何将它们全部转换为 [0,0,0]
?
import numpy as np
a = np.ones((3,5,5))
a[0,2:4,2:4] = 150
a[0,0:1,0:1] = 150 #important!
a[1,2:4,2:4] = 160
a[2,2:4,2:4] = 170
print a
预期结果应该是:
[[[ 1. 1. 1. 1. 1.]
[ 1. 1. 1. 1. 1.]
[ 1. 1. 0. 0. 1.]
[ 1. 1. 0. 0. 1.]
[ 1. 1. 1. 1. 1.]]
[[ 1. 1. 1. 1. 1.]
[ 1. 1. 1. 1. 1.]
[ 1. 1. 0. 0. 1.]
[ 1. 1. 0. 0. 1.]
[ 1. 1. 1. 1. 1.]]
[[ 1. 1. 1. 1. 1.]
[ 1. 1. 1. 1. 1.]
[ 1. 1. 0. 0. 1.]
[ 1. 1. 0. 0. 1.]
[ 1. 1. 1. 1. 1.]]]
首先我会转换成一堆三元组:
b = np.reshape(a.transpose(2, 1, 0), [25,3])
然后找到你想要的值:
idx = np.where((b == np.array([150, 160, 170])).all(axis=1))
并替换为您想要的任何值:
b[idx] = 0
最后转换回原来的形状:
c = np.reshape(b, [5, 5, 3]).transpose(2, 1, 0)
构造你的a
:
In [48]: a=np.ones((3,5,5))
In [49]: a[0,2:4,2:4]=150
In [50]: a[1,2:4,2:4]=160
In [51]: a[2,2:4,2:4]=170
In [52]: a
Out[52]:
array([[[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 150., 150., 1.],
[ 1., 1., 150., 150., 1.],
[ 1., 1., 1., 1., 1.]],
[[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 160., 160., 1.],
[ 1., 1., 160., 160., 1.],
[ 1., 1., 1., 1., 1.]],
[[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 170., 170., 1.],
[ 1., 1., 170., 170., 1.],
[ 1., 1., 1., 1., 1.]]])
第一个维度上的值为 [150,160,170]
的所有位置的布尔值。关键是将其扩展为 3d,形状 (3,1,1)
可以广播到 (3,5,5)
并与 a
:
进行比较
In [53]: I = a==np.array([150,160,170])[:,None,None]
In [54]: I
Out[54]:
array([[[False, False, False, False, False],
[False, False, False, False, False],
[False, False, True, True, False],
[False, False, True, True, False],
[False, False, False, False, False]],
[[False, False, False, False, False],
[False, False, False, False, False],
[False, False, True, True, False],
[False, False, True, True, False],
[False, False, False, False, False]],
[[False, False, False, False, False],
[False, False, False, False, False],
[False, False, True, True, False],
[False, False, True, True, False],
[False, False, False, False, False]]], dtype=bool)
现在可以轻松地将所有值 True
的插槽更改为 0
:
In [55]: a[I]=0
In [56]: a
Out[56]:
array([[[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 0., 0., 1.],
[ 1., 1., 0., 0., 1.],
[ 1., 1., 1., 1., 1.]],
[[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 0., 0., 1.],
[ 1., 1., 0., 0., 1.],
[ 1., 1., 1., 1., 1.]],
[[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 0., 0., 1.],
[ 1., 1., 0., 0., 1.],
[ 1., 1., 1., 1., 1.]]])
查看已删除答案的评论,我发现您真的想要一个所有 3 个值都匹配的案例。也就是说,与您的示例相反,可能还有其他插槽 a[0,...]
is 150 等您不想更改。
您仍然可以使用此 I
,只需在第一个轴上取一个 all
:
In [58]: a[:,I.all(axis=0)]=2
In [59]: a
Out[59]:
array([[[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 2., 2., 1.],
[ 1., 1., 2., 2., 1.],
[ 1., 1., 1., 1., 1.]],
[[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 2., 2., 1.],
[ 1., 1., 2., 2., 1.],
[ 1., 1., 1., 1., 1.]],
[[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 2., 2., 1.],
[ 1., 1., 2., 2., 1.],
[ 1., 1., 1., 1., 1.]]])
从概念上讲,我的答案与公认的答案没有什么不同。这会将数组重塑为 2d,因此可以使用 1d [150,160,170]
进行匹配。实际上它会自动重塑为 (1,3)
可以再次广播 (25,3)
数组。转置和重塑是标准化此类问题格式的便捷方法,尽管通常不是必需的。
将最后一个操作拆分可能会有所帮助:
In [60]: J=I.all(axis=0)
In [61]: J
Out[61]:
array([[False, False, False, False, False],
[False, False, False, False, False],
[False, False, True, True, False],
[False, False, True, True, False],
[False, False, False, False, False]], dtype=bool)
In [62]: a[:, J] = 3
或使用 np.where
将布尔数组转换为 2 个索引列表:
In [73]: jj=np.where(J)
In [74]: jj
Out[74]: (array([2, 2, 3, 3], dtype=int32), array([2, 3, 2, 3], dtype=int32))
In [75]: a[:, jj[0], jj[1]] = 4
a[:,jj]
不起作用,但 a[(slice(None),)+jj]
起作用。最后一个表达式构造一个 3 元素元组,相当于 [75] 的。
我还可以将 J
扩展到与 a
:
匹配的大小和形状
In [90]: K=J[None,...].repeat(3,0)
In [91]: K
Out[91]:
array([[[False, False, False, False, False],
[False, False, False, False, False],
[False, False, True, True, False],
[False, False, True, True, False],
[False, False, False, False, False]],
[[False, False, False, False, False],
....]], dtype=bool)
并使用 a[K]
.
我有一个 3d numpy 数组如下:
(3L, 5L, 5L)
如果一个元素在 3d 位置,例如 [150, 160, 170]
存在。如何将它们全部转换为 [0,0,0]
?
import numpy as np
a = np.ones((3,5,5))
a[0,2:4,2:4] = 150
a[0,0:1,0:1] = 150 #important!
a[1,2:4,2:4] = 160
a[2,2:4,2:4] = 170
print a
预期结果应该是:
[[[ 1. 1. 1. 1. 1.]
[ 1. 1. 1. 1. 1.]
[ 1. 1. 0. 0. 1.]
[ 1. 1. 0. 0. 1.]
[ 1. 1. 1. 1. 1.]]
[[ 1. 1. 1. 1. 1.]
[ 1. 1. 1. 1. 1.]
[ 1. 1. 0. 0. 1.]
[ 1. 1. 0. 0. 1.]
[ 1. 1. 1. 1. 1.]]
[[ 1. 1. 1. 1. 1.]
[ 1. 1. 1. 1. 1.]
[ 1. 1. 0. 0. 1.]
[ 1. 1. 0. 0. 1.]
[ 1. 1. 1. 1. 1.]]]
首先我会转换成一堆三元组:
b = np.reshape(a.transpose(2, 1, 0), [25,3])
然后找到你想要的值:
idx = np.where((b == np.array([150, 160, 170])).all(axis=1))
并替换为您想要的任何值:
b[idx] = 0
最后转换回原来的形状:
c = np.reshape(b, [5, 5, 3]).transpose(2, 1, 0)
构造你的a
:
In [48]: a=np.ones((3,5,5))
In [49]: a[0,2:4,2:4]=150
In [50]: a[1,2:4,2:4]=160
In [51]: a[2,2:4,2:4]=170
In [52]: a
Out[52]:
array([[[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 150., 150., 1.],
[ 1., 1., 150., 150., 1.],
[ 1., 1., 1., 1., 1.]],
[[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 160., 160., 1.],
[ 1., 1., 160., 160., 1.],
[ 1., 1., 1., 1., 1.]],
[[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 170., 170., 1.],
[ 1., 1., 170., 170., 1.],
[ 1., 1., 1., 1., 1.]]])
第一个维度上的值为 [150,160,170]
的所有位置的布尔值。关键是将其扩展为 3d,形状 (3,1,1)
可以广播到 (3,5,5)
并与 a
:
In [53]: I = a==np.array([150,160,170])[:,None,None]
In [54]: I
Out[54]:
array([[[False, False, False, False, False],
[False, False, False, False, False],
[False, False, True, True, False],
[False, False, True, True, False],
[False, False, False, False, False]],
[[False, False, False, False, False],
[False, False, False, False, False],
[False, False, True, True, False],
[False, False, True, True, False],
[False, False, False, False, False]],
[[False, False, False, False, False],
[False, False, False, False, False],
[False, False, True, True, False],
[False, False, True, True, False],
[False, False, False, False, False]]], dtype=bool)
现在可以轻松地将所有值 True
的插槽更改为 0
:
In [55]: a[I]=0
In [56]: a
Out[56]:
array([[[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 0., 0., 1.],
[ 1., 1., 0., 0., 1.],
[ 1., 1., 1., 1., 1.]],
[[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 0., 0., 1.],
[ 1., 1., 0., 0., 1.],
[ 1., 1., 1., 1., 1.]],
[[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 0., 0., 1.],
[ 1., 1., 0., 0., 1.],
[ 1., 1., 1., 1., 1.]]])
查看已删除答案的评论,我发现您真的想要一个所有 3 个值都匹配的案例。也就是说,与您的示例相反,可能还有其他插槽 a[0,...]
is 150 等您不想更改。
您仍然可以使用此 I
,只需在第一个轴上取一个 all
:
In [58]: a[:,I.all(axis=0)]=2
In [59]: a
Out[59]:
array([[[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 2., 2., 1.],
[ 1., 1., 2., 2., 1.],
[ 1., 1., 1., 1., 1.]],
[[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 2., 2., 1.],
[ 1., 1., 2., 2., 1.],
[ 1., 1., 1., 1., 1.]],
[[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 2., 2., 1.],
[ 1., 1., 2., 2., 1.],
[ 1., 1., 1., 1., 1.]]])
从概念上讲,我的答案与公认的答案没有什么不同。这会将数组重塑为 2d,因此可以使用 1d [150,160,170]
进行匹配。实际上它会自动重塑为 (1,3)
可以再次广播 (25,3)
数组。转置和重塑是标准化此类问题格式的便捷方法,尽管通常不是必需的。
将最后一个操作拆分可能会有所帮助:
In [60]: J=I.all(axis=0)
In [61]: J
Out[61]:
array([[False, False, False, False, False],
[False, False, False, False, False],
[False, False, True, True, False],
[False, False, True, True, False],
[False, False, False, False, False]], dtype=bool)
In [62]: a[:, J] = 3
或使用 np.where
将布尔数组转换为 2 个索引列表:
In [73]: jj=np.where(J)
In [74]: jj
Out[74]: (array([2, 2, 3, 3], dtype=int32), array([2, 3, 2, 3], dtype=int32))
In [75]: a[:, jj[0], jj[1]] = 4
a[:,jj]
不起作用,但 a[(slice(None),)+jj]
起作用。最后一个表达式构造一个 3 元素元组,相当于 [75] 的。
我还可以将 J
扩展到与 a
:
In [90]: K=J[None,...].repeat(3,0)
In [91]: K
Out[91]:
array([[[False, False, False, False, False],
[False, False, False, False, False],
[False, False, True, True, False],
[False, False, True, True, False],
[False, False, False, False, False]],
[[False, False, False, False, False],
....]], dtype=bool)
并使用 a[K]
.