根据二维索引数组设置二维数组元素
Set 2D array elements based on 2D index array
在 Python 中,假设您有一个形状为 (N,4,4) 的二维零点数组:
z = array([[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]],
[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]]])
你有一个二维索引数组:
i = array([[1, 1, 1, 1],
[1, 0, 0, 0],
[0, 0, 1, 1],
[1, 1, 1, 0]])
和一些有价值的二维数组:
v = array([[ 2., 4., 10., 7.],
[10., 9., 9., 2.],
[ 3., 8., 8., 8.],
[ 8., 6., 10., 1.]])
有没有办法用 v
的值填充 z
的元素,但在 i
表示的切片中,而不使用循环?
注意:有没有办法以可扩展的方式做到这一点,这样如果你有一个 N 通道数组 z
,其中 N>>1,你就不需要直接索引 z[i]
用 v
?
中的值填充时
为清楚起见,生成的 z
数组如下所示:
z = array([[[0., 0., 0., 0.],
[0., 9., 9., 2.],
[3., 8., 0., 0.],
[0., 0., 0., 1.]],
[[2., 4., 10., 7.],
[10., 0., 0., 0.],
[0., 0., 8., 8.],
[8, 6., 10., 0.]]])
显然,使用类似的东西:
z = v[i,:,:]
永远行不通,但也许有一种方法可以使用 rows, cols
来做到这一点?
非常感谢!
编辑:
为清楚起见,这里有一个类似的示例,但对于评论中要求的 3D z
:
z = array([[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]],
[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]],
[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]]])
i = array([[2, 1, 2, 1],
[1, 1, 2, 1],
[1, 1, 1, 1],
[1, 0, 0, 1]])
v = array([[5., 5., 0., 4.],
[4., 6., 8., 3.],
[4., 0., 4., 8.],
[7., 6., 5., 7.]])
z
会变成:
z = array([[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 6., 5., 0.]],
[[0., 5., 0., 4.],
[4., 6., 0., 3.],
[4., 0., 4., 8.],
[7., 0., 0., 7.]],
[[5., 0., 0., 0.],
[0., 0., 8., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]]])
你总是可以使用蒙版和相乘:
from numpy import array
z = array([[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]],
[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]]])
i = array([[1, 1, 1, 1],
[1, 0, 0, 0],
[0, 0, 1, 1],
[1, 1, 1, 0]])
v = array([[ 2., 4., 10., 7.],
[10., 9., 9., 2.],
[ 3., 8., 8., 8.],
[ 8., 6., 10., 1.]])
z[0] = ~i.astype(bool)*v
z[1] = i.astype(bool)*v
输出:
z =
array([[[ 0., 0., 0., 0.],
[ 0., 9., 9., 2.],
[ 3., 8., 0., 0.],
[ 0., 0., 0., 1.]],
[[ 2., 4., 10., 7.],
[10., 0., 0., 0.],
[ 0., 0., 8., 8.],
[ 8., 6., 10., 0.]]])
对于更一般的情况:
for ax in np.unique(i):
mask = i == ax
z[ax] = mask*v
print(z)
输出:
[[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 6. 5. 0.]]
[[0. 5. 0. 4.]
[4. 6. 0. 3.]
[4. 0. 4. 8.]
[7. 0. 0. 7.]]
[[5. 0. 0. 0.]
[0. 0. 8. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]]
注意:这里我假设 i
中的值与 z
中的通道相同。如果不同,而不是np.unique,你可以尝试:
for i_val,ax in zip(np.unique(i),range(z.shape[0]))::
mask = i == i_val
z[ax] = mask*v
编辑
一行是:
>>> z = np.array([*map(i.__eq__,np.unique(i))])*np.array([v]*z.shape[0])
>>> z
array([[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 6., 5., 0.]],
[[0., 5., 0., 4.],
[4., 6., 0., 3.],
[4., 0., 4., 8.],
[7., 0., 0., 7.]],
[[5., 0., 0., 0.],
[0., 0., 8., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]]])
可能使用numpy.where
:
z[0] = np.where(i, z[0], v)
z[1] = np.where(1 - i, z[1], v)
输出:
array([[[ 0., 0., 0., 0.],
[ 0., 9., 9., 2.],
[ 3., 8., 0., 0.],
[ 0., 0., 0., 1.]],
[[ 2., 4., 10., 7.],
[10., 0., 0., 0.],
[ 0., 0., 8., 8.],
[ 8., 6., 10., 0.]]])
更新后,如果 i
持有要更改的 z
的索引(与示例中的 0 和 1 相反),它可以轻松缩放为:
for N in range(z.shape[0]):
z[N] = np.where(i == N, v, z[N])
或者,如果你真的想避免所有循环:
z = np.where(i == (np.where(np.ones(len(z.reshape(-1))) == 1)[0] // (z.shape[1] * z.shape[2])).reshape(z.shape), v, z)
输出:
array([[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 6., 5., 0.]],
[[0., 5., 0., 4.],
[4., 6., 0., 3.],
[4., 0., 4., 8.],
[7., 0., 0., 7.]],
[[5., 0., 0., 0.],
[0., 0., 8., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]]])
没有 numpy 的东西更复杂:
r = list(zip(i,v))
z[0] = [[l2[i] if l1[i]==0 else 0 for i in range(4)] for l1, l2 in r ]
z[1] = [[l2[i] if l1[i]==1 else 0 for i in range(4)] for l1, l2 in r ]
在 Python 中,假设您有一个形状为 (N,4,4) 的二维零点数组:
z = array([[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]],
[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]]])
你有一个二维索引数组:
i = array([[1, 1, 1, 1],
[1, 0, 0, 0],
[0, 0, 1, 1],
[1, 1, 1, 0]])
和一些有价值的二维数组:
v = array([[ 2., 4., 10., 7.],
[10., 9., 9., 2.],
[ 3., 8., 8., 8.],
[ 8., 6., 10., 1.]])
有没有办法用 v
的值填充 z
的元素,但在 i
表示的切片中,而不使用循环?
注意:有没有办法以可扩展的方式做到这一点,这样如果你有一个 N 通道数组 z
,其中 N>>1,你就不需要直接索引 z[i]
用 v
?
为清楚起见,生成的 z
数组如下所示:
z = array([[[0., 0., 0., 0.],
[0., 9., 9., 2.],
[3., 8., 0., 0.],
[0., 0., 0., 1.]],
[[2., 4., 10., 7.],
[10., 0., 0., 0.],
[0., 0., 8., 8.],
[8, 6., 10., 0.]]])
显然,使用类似的东西:
z = v[i,:,:]
永远行不通,但也许有一种方法可以使用 rows, cols
来做到这一点?
非常感谢!
编辑:
为清楚起见,这里有一个类似的示例,但对于评论中要求的 3D z
:
z = array([[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]],
[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]],
[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]]])
i = array([[2, 1, 2, 1],
[1, 1, 2, 1],
[1, 1, 1, 1],
[1, 0, 0, 1]])
v = array([[5., 5., 0., 4.],
[4., 6., 8., 3.],
[4., 0., 4., 8.],
[7., 6., 5., 7.]])
z
会变成:
z = array([[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 6., 5., 0.]],
[[0., 5., 0., 4.],
[4., 6., 0., 3.],
[4., 0., 4., 8.],
[7., 0., 0., 7.]],
[[5., 0., 0., 0.],
[0., 0., 8., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]]])
你总是可以使用蒙版和相乘:
from numpy import array
z = array([[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]],
[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]]])
i = array([[1, 1, 1, 1],
[1, 0, 0, 0],
[0, 0, 1, 1],
[1, 1, 1, 0]])
v = array([[ 2., 4., 10., 7.],
[10., 9., 9., 2.],
[ 3., 8., 8., 8.],
[ 8., 6., 10., 1.]])
z[0] = ~i.astype(bool)*v
z[1] = i.astype(bool)*v
输出:
z =
array([[[ 0., 0., 0., 0.],
[ 0., 9., 9., 2.],
[ 3., 8., 0., 0.],
[ 0., 0., 0., 1.]],
[[ 2., 4., 10., 7.],
[10., 0., 0., 0.],
[ 0., 0., 8., 8.],
[ 8., 6., 10., 0.]]])
对于更一般的情况:
for ax in np.unique(i):
mask = i == ax
z[ax] = mask*v
print(z)
输出:
[[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 6. 5. 0.]]
[[0. 5. 0. 4.]
[4. 6. 0. 3.]
[4. 0. 4. 8.]
[7. 0. 0. 7.]]
[[5. 0. 0. 0.]
[0. 0. 8. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]]
注意:这里我假设 i
中的值与 z
中的通道相同。如果不同,而不是np.unique,你可以尝试:
for i_val,ax in zip(np.unique(i),range(z.shape[0]))::
mask = i == i_val
z[ax] = mask*v
编辑
一行是:
>>> z = np.array([*map(i.__eq__,np.unique(i))])*np.array([v]*z.shape[0])
>>> z
array([[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 6., 5., 0.]],
[[0., 5., 0., 4.],
[4., 6., 0., 3.],
[4., 0., 4., 8.],
[7., 0., 0., 7.]],
[[5., 0., 0., 0.],
[0., 0., 8., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]]])
可能使用numpy.where
:
z[0] = np.where(i, z[0], v)
z[1] = np.where(1 - i, z[1], v)
输出:
array([[[ 0., 0., 0., 0.],
[ 0., 9., 9., 2.],
[ 3., 8., 0., 0.],
[ 0., 0., 0., 1.]],
[[ 2., 4., 10., 7.],
[10., 0., 0., 0.],
[ 0., 0., 8., 8.],
[ 8., 6., 10., 0.]]])
更新后,如果 i
持有要更改的 z
的索引(与示例中的 0 和 1 相反),它可以轻松缩放为:
for N in range(z.shape[0]):
z[N] = np.where(i == N, v, z[N])
或者,如果你真的想避免所有循环:
z = np.where(i == (np.where(np.ones(len(z.reshape(-1))) == 1)[0] // (z.shape[1] * z.shape[2])).reshape(z.shape), v, z)
输出:
array([[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 6., 5., 0.]],
[[0., 5., 0., 4.],
[4., 6., 0., 3.],
[4., 0., 4., 8.],
[7., 0., 0., 7.]],
[[5., 0., 0., 0.],
[0., 0., 8., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]]])
没有 numpy 的东西更复杂:
r = list(zip(i,v))
z[0] = [[l2[i] if l1[i]==0 else 0 for i in range(4)] for l1, l2 in r ]
z[1] = [[l2[i] if l1[i]==1 else 0 for i in range(4)] for l1, l2 in r ]