用位于 Mx2 numpy 数组中的元素替换 Nx3x2 numpy 数组中的元素
Replace elements in an Nx3x2 numpy array with elements located in an Mx2 numpy array
我有以下 xy
代表一些三角形顶点位置的 numpy 数组:
array([[[ 0.30539728, 49.82845203],
[ 0.67235022, 49.95042185],
[ 0.268982 , 49.95195348]],
[[ 0.268982 , 49.95195348],
[ 0.67235022, 49.95042185],
[ 0.27000135, 50.16334035]],
...
[[ 1.00647459, 50.25958169],
[ 0.79479121, 50.3010079 ],
[ 0.67235022, 49.95042185]],
[[ 0.79479121, 50.3010079 ],
[ 0.6886783 , 50.25867683],
[ 0.67235022, 49.95042185]]])
在这里,它是一个形状为 (10, 3, 2)
的数组,但它也可以是 (5, 3, 2)
或 (18, 3, 2)
,随你便。在任何情况下,它的形状都是 (N, 3, 2)
。
我有另一个形状 (4, 2)
的 numpy 数组 to_replace
但它也可以是 (6, 2)
或 (7, 2)
,但总是形状 (M, 2)
:
array([[ 1.08267406, 49.88690993],
[ 1.1028248 , 50.01440407],
[ 0.74114309, 49.73183549],
[ 1.08267406, 49.88690993]])
它表示可以在我的第一个数组中找到的坐标对的位置。请注意,这些对中的每一对在 xy
中至少出现一次,但也可能出现不止一次。
最后,我有第三个数组 replace_by
,其形状为 (8,)
(或根据上面的指示形状为 (M*2)
),其值旨在准确替换 [=19= 中包含的值] 在我的第一个 xy
数组中。它看起来像这样:
array([ 0.87751214, 49.91866589, 0.88758751, 49.98241296, 0.70674665, 49.84112867, 0.87751214, 49.91866589])
所以基本上 xy
中的所有对 [1.08267406, 49.88690993]
都应该替换为 [0.87751214, 49.91866589]
例如。
我当前的代码看起来像这样,但只有当 to_replace
和 replace_by
的形状严格为 (2, 2)
.
时它才有效
indices = (xy == to_replace[:, None][:, None])[0]
xy[indices] = replace_by
我 at a of answers 并且实际上受到了其中一些的启发,但我仍然无法让它发挥作用。
您可以使用 numpy.isclose 比较行,然后使用 .all(axis=2)
查找所有最后一行的相同之处。 Numpy 将广播每一行以适应 xy
形状。
import numpy as np
xy = np.array([[[ 0.30539728, 49.82845203],
[ 0.67235022, 49.95042185],
[ 0.268982 , 49.95195348]],
[[ 0.268982 , 49.95195348],
[ 0.67235022, 49.95042185],
[ 0.27000135, 50.16334035]],
[[ 1.00647459, 50.25958169],
[ 0.79479121, 50.3010079 ],
[ 0.67235022, 49.95042185]],
[[ 0.79479121, 50.3010079 ],
[ 0.6886783 , 50.25867683],
[ 0.67235022, 49.95042185]]])
xy_start = xy.copy()
to_replace = np.array([[ 1.08267406, 49.88690993],
[ 1.1028248 , 50.01440407],
# [ 0.74114309, 49.73183549],
[ 0.6886783 , 50.25867683],
[ 1.08267406, 49.88690993]])
replace_by = np.array([ 0.87751214, 49.91866589, 0.88758751, 49.98241296, 0.70674665, 49.84112867, 0.87751214, 49.91866589])
replace_by_reshaped = replace_by.reshape(-1, 2)
for i, row in enumerate(to_replace):
xy[np.isclose(xy, row).all(axis=2)] = replace_by_reshaped[i]
print(xy_start)
# [[[ 0.30539728 49.82845203]
# [ 0.67235022 49.95042185]
# [ 0.268982 49.95195348]]
# [[ 0.268982 49.95195348]
# [ 0.67235022 49.95042185]
# [ 0.27000135 50.16334035]]
# [[ 1.00647459 50.25958169]
# [ 0.79479121 50.3010079 ]
# [ 0.67235022 49.95042185]]
# [[ 0.79479121 50.3010079 ]
# [ 0.6886783 50.25867683]
# [ 0.67235022 49.95042185]]]
print(xy)
# [[[ 0.30539728 49.82845203]
# [ 0.67235022 49.95042185]
# [ 0.268982 49.95195348]]
# [[ 0.268982 49.95195348]
# [ 0.67235022 49.95042185]
# [ 0.27000135 50.16334035]]
# [[ 1.00647459 50.25958169]
# [ 0.79479121 50.3010079 ]
# [ 0.67235022 49.95042185]]
# [[ 0.79479121 50.3010079 ]
# [ 0.70674665 49.84112867]
# [ 0.67235022 49.95042185]]]
编辑
.all(axis=2)
shrink axis=2 to True
if all values along axis=2 are True
and False
else.我认为 2d 的小例子清楚地说明了这里发生的事情。
>>> import numpy as np
>>> a = np.array([[0, 1], [0, 2], [3, 4]])
>>> a
array([[0, 1],
[0, 2],
[3, 4]])
>>> np.isclose(a, [0, 1])
array([[ True, True],
[ True, False],
[False, False]])
>>> np.isclose(a, [0, 1]).all(axis=1)
array([ True, False, False])
>>> a[np.isclose(a, [0, 1]).all(axis=1)]
array([[0, 1]])
>>> a[np.isclose(a, [0, 1]).all(axis=1)] = [12, 14]
>>> a
array([[12, 14],
[ 0, 2],
[ 3, 4]])
numpy-indexed 包(免责声明:我是其作者)包含以矢量化和优雅的方式解决此问题的功能。
鉴于您定义的数组,这一行应该可以解决问题:
import numpy_indexed as npi
npi.remap(xy.reshape(-1, 2), to_replace, replace_by.reshape(-1, 2)).reshape(-1, 3, 2)
我有以下 xy
代表一些三角形顶点位置的 numpy 数组:
array([[[ 0.30539728, 49.82845203],
[ 0.67235022, 49.95042185],
[ 0.268982 , 49.95195348]],
[[ 0.268982 , 49.95195348],
[ 0.67235022, 49.95042185],
[ 0.27000135, 50.16334035]],
...
[[ 1.00647459, 50.25958169],
[ 0.79479121, 50.3010079 ],
[ 0.67235022, 49.95042185]],
[[ 0.79479121, 50.3010079 ],
[ 0.6886783 , 50.25867683],
[ 0.67235022, 49.95042185]]])
在这里,它是一个形状为 (10, 3, 2)
的数组,但它也可以是 (5, 3, 2)
或 (18, 3, 2)
,随你便。在任何情况下,它的形状都是 (N, 3, 2)
。
我有另一个形状 (4, 2)
的 numpy 数组 to_replace
但它也可以是 (6, 2)
或 (7, 2)
,但总是形状 (M, 2)
:
array([[ 1.08267406, 49.88690993],
[ 1.1028248 , 50.01440407],
[ 0.74114309, 49.73183549],
[ 1.08267406, 49.88690993]])
它表示可以在我的第一个数组中找到的坐标对的位置。请注意,这些对中的每一对在 xy
中至少出现一次,但也可能出现不止一次。
最后,我有第三个数组 replace_by
,其形状为 (8,)
(或根据上面的指示形状为 (M*2)
),其值旨在准确替换 [=19= 中包含的值] 在我的第一个 xy
数组中。它看起来像这样:
array([ 0.87751214, 49.91866589, 0.88758751, 49.98241296, 0.70674665, 49.84112867, 0.87751214, 49.91866589])
所以基本上 xy
中的所有对 [1.08267406, 49.88690993]
都应该替换为 [0.87751214, 49.91866589]
例如。
我当前的代码看起来像这样,但只有当 to_replace
和 replace_by
的形状严格为 (2, 2)
.
indices = (xy == to_replace[:, None][:, None])[0]
xy[indices] = replace_by
我
您可以使用 numpy.isclose 比较行,然后使用 .all(axis=2)
查找所有最后一行的相同之处。 Numpy 将广播每一行以适应 xy
形状。
import numpy as np
xy = np.array([[[ 0.30539728, 49.82845203],
[ 0.67235022, 49.95042185],
[ 0.268982 , 49.95195348]],
[[ 0.268982 , 49.95195348],
[ 0.67235022, 49.95042185],
[ 0.27000135, 50.16334035]],
[[ 1.00647459, 50.25958169],
[ 0.79479121, 50.3010079 ],
[ 0.67235022, 49.95042185]],
[[ 0.79479121, 50.3010079 ],
[ 0.6886783 , 50.25867683],
[ 0.67235022, 49.95042185]]])
xy_start = xy.copy()
to_replace = np.array([[ 1.08267406, 49.88690993],
[ 1.1028248 , 50.01440407],
# [ 0.74114309, 49.73183549],
[ 0.6886783 , 50.25867683],
[ 1.08267406, 49.88690993]])
replace_by = np.array([ 0.87751214, 49.91866589, 0.88758751, 49.98241296, 0.70674665, 49.84112867, 0.87751214, 49.91866589])
replace_by_reshaped = replace_by.reshape(-1, 2)
for i, row in enumerate(to_replace):
xy[np.isclose(xy, row).all(axis=2)] = replace_by_reshaped[i]
print(xy_start)
# [[[ 0.30539728 49.82845203]
# [ 0.67235022 49.95042185]
# [ 0.268982 49.95195348]]
# [[ 0.268982 49.95195348]
# [ 0.67235022 49.95042185]
# [ 0.27000135 50.16334035]]
# [[ 1.00647459 50.25958169]
# [ 0.79479121 50.3010079 ]
# [ 0.67235022 49.95042185]]
# [[ 0.79479121 50.3010079 ]
# [ 0.6886783 50.25867683]
# [ 0.67235022 49.95042185]]]
print(xy)
# [[[ 0.30539728 49.82845203]
# [ 0.67235022 49.95042185]
# [ 0.268982 49.95195348]]
# [[ 0.268982 49.95195348]
# [ 0.67235022 49.95042185]
# [ 0.27000135 50.16334035]]
# [[ 1.00647459 50.25958169]
# [ 0.79479121 50.3010079 ]
# [ 0.67235022 49.95042185]]
# [[ 0.79479121 50.3010079 ]
# [ 0.70674665 49.84112867]
# [ 0.67235022 49.95042185]]]
编辑
.all(axis=2)
shrink axis=2 to True
if all values along axis=2 are True
and False
else.我认为 2d 的小例子清楚地说明了这里发生的事情。
>>> import numpy as np
>>> a = np.array([[0, 1], [0, 2], [3, 4]])
>>> a
array([[0, 1],
[0, 2],
[3, 4]])
>>> np.isclose(a, [0, 1])
array([[ True, True],
[ True, False],
[False, False]])
>>> np.isclose(a, [0, 1]).all(axis=1)
array([ True, False, False])
>>> a[np.isclose(a, [0, 1]).all(axis=1)]
array([[0, 1]])
>>> a[np.isclose(a, [0, 1]).all(axis=1)] = [12, 14]
>>> a
array([[12, 14],
[ 0, 2],
[ 3, 4]])
numpy-indexed 包(免责声明:我是其作者)包含以矢量化和优雅的方式解决此问题的功能。
鉴于您定义的数组,这一行应该可以解决问题:
import numpy_indexed as npi
npi.remap(xy.reshape(-1, 2), to_replace, replace_by.reshape(-1, 2)).reshape(-1, 3, 2)