使用索引列表列表对列进行切片并获取行向向量长度

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

我有一个 NxM 数组,以及我想用来对数组进行切片的列索引集的任意列表。例如,3x3 数组

my_arr = np.array([[1, 2, 3], [1, 2, 3], [1, 2, 3]])

和索引集

my_idxs = [[0, 1], [2]]

我想使用索引对从数组中选择相应的列,并使用

np.linalg.norm()
获取(行方向)向量的长度。我想对所有索引对执行此操作。给定上述数组和索引集列表,这应该给出:

[[2.23606797749979, 3],
 [2.23606797749979, 3],
 [2.23606797749979, 3]]

当所有集合具有相同数量的索引时(例如,使用

my_idxs = [[0, 1], [1, 2]]
我可以简单地使用
np.linalg.norm(my_arr[:, my_idxs], axis=1)
:

[[2.23606797749979, 3.605551275463989],
 [2.23606797749979, 3.605551275463989],
 [2.23606797749979, 3.605551275463989]]

但是,当它们不是时(如

my_idxs = [[0, 1], [2]]
的情况,不同的索引列表长度在切片时会产生错误,因为索引集数组的形状会不规则。有没有办法实现单行选项,而不需要循环遍历索引集列表并单独处理每个索引集?

python numpy numpy-slicing
2个回答
0
投票

你可以尝试:

my_arr = np.array([[1, 2, 3], [1, 2, 3], [1, 2, 3]])
my_idxs = [[0, 1], [2]]

out = np.c_[*[np.linalg.norm(my_arr[:, i], axis=1) for i in my_idxs]]
print(out)

打印:

[[2.23606798 3.        ]
 [2.23606798 3.        ]
 [2.23606798 3.        ]]

0
投票

您希望计算通过使用不同长度的索引列表从 NumPy 数组中选择列而形成的向量的行范数。您的目标是有效地实现这一点,最好不要在索引集上使用显式循环。

解决方案: 您可以使用列表理解来解决不同长度的索引集带来的挑战。虽然这不是单个切片操作(由于形状不规则,这是不可能的),但它是一种利用 NumPy 操作功能的简洁方法。

以下是实现此方法的方法:

import numpy as np

# Define your array
my_arr = np.array([[1, 2, 3], [1, 2, 3], [1, 2, 3]])

# Define your list of index sets
my_idxs = [[0, 1], [2]]

# Compute the norm for each set of indices using a list comprehension
result = np.array([np.linalg.norm(my_arr[:, idx], axis=1) for idx in my_idxs]).T

# Print the result
print(result)

输出:

 [[2.23606798 3.        ]
 [2.23606798 3.        ]
 [2.23606798 3.        ]]

说明:

列表理解:循环遍历 my_idxs 中的每组索引。对于每个集合,它从 my_arr 中选择相应的列并计算行间的范数 (axis=1)。

Transpose (T):列表理解的结果是一个列表,其中每个元素都是一个数组,表示为每组索引计算的范数。 np.array(...) 将此列表转换为 2D NumPy 数组。然后应用转置来正确对齐输出,以便每一行对应于 my_arr 的原始行,每一列代表每个索引集的范数结果。

这种方法可以有效地满足您从数组列的子集计算向量范数的要求,即使子集的长度不同。它最大限度地利用 NumPy 的功能,以避免与循环数组行相关的显式性能损失。

结论: 尽管由于会导致尺寸不均匀,直接将不同索引长度的切片分解为单个操作是不可行的,但提供的解决方案使用紧凑而高效的 Python 代码行实现了您的目标。

© www.soinside.com 2019 - 2024. All rights reserved.