将Nx3x2 numpy数组中的元素替换为Mx2 numpy数组中的元素。

问题描述 投票:0回答:1

我有以下几点 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).我有另一个numpy数组 to_replace 形状 (4, 2) 但也可能是 (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) 基于上面的说明),哪些值是用来准确地替换包含在 to_replace 在我第一次 xy 阵列。它看起来像这样。

array([ 0.87751214, 49.91866589,  0.88758751, 49.98241296,  0.70674665, 49.84112867,  0.87751214, 49.91866589])

所以基本上所有的对 [1.08267406, 49.88690993]xy 应改为 [0.87751214, 49.91866589] 比如说,我现在的代码是这样的。

我现在的代码是这样的,但只有在以下情况下才有效 to_replacereplace_by 严形 (2, 2).

indices = (xy == to_replace[:, None][:, None])[0]
xy[indices] = replace_by

I 已经 看起来 就在 数目答案 其实也受到了其中一些启发,但我还是不能让它工作。

python python-3.x numpy numpy-ndarray array-broadcasting
1个回答
1
投票

您可以使用 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) 缩小轴=2至 True 如果沿轴线=2的所有数值都是 TrueFalse 别的。我想小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]])

0
投票

指数化 包(声明:我是它的作者)包含了以矢量化和优雅的方式解决这个问题的功能。

考虑到你所定义的数组,这个单行本应该可以解决这个问题。

import numpy_indexed as npi    
npi.remap(xy.reshape(-1, 2), to_replace, replace_by.reshape(-1, 2)).reshape(-1, 3, 2)
© www.soinside.com 2019 - 2024. All rights reserved.