通过 Python 中的索引列表访问 Matrix 的元素,以在没有 for 循环的情况下将 max(val, 0.5) 应用于每个值

Access elements of a Matrix by a list of indices in Python to apply a max(val, 0.5) to each value without a for loop

我知道如何通过索引访问向量中的元素:

test = numpy.array([1,2,3,4,5,6])
indices = list([1,3,5])
print(test[indices])

给出正确答案:[2 4 6]

但我正在尝试使用二维矩阵做同样的事情,例如:

currentGrid = numpy.array(  [[0,   0.1],
                             [0.9, 0.9],
                             [0.1, 0.1]])
indices = list([(0,0),(1,1)])
print(currentGrid[indices])

对于矩阵中 (0,0) 处的值和 (1,1) 处的值,这应该向我显示“[0.0 0.9]”。但它显示的是“[0.1 0.1]”。另外,如果我尝试将 3 个索引与 :

一起使用
indices = list([(0,0),(1,1),(0,2)])

我现在收到以下错误:

Traceback (most recent call last):
  File "main.py", line 43, in <module>
    print(currentGrid[indices])
IndexError: too many indices for array

我最终需要对这些索引处的所有元素应用一个简单的 max() 操作,并且为了优化目的需要最快的方法。

我做错了什么?我如何访问矩阵中的特定元素以非常有效的方式对它们执行一些操作(不使用列表理解或循环)。

问题在于您传递给数组的索引的排列方式。如果您的数组是二维的,则您的索引必须是两个列表,一个包含垂直索引,另一个包含水平索引。例如:

idx_i, idx_j = zip(*[(0, 0), (1, 1), (0, 2)])
print currentGrid[idx_j, idx_i]
# [0.0, 0.9, 0.1]

请注意,索引数组时的第一个元素是最后一个维度,例如:(y, x)。我假设你将你的定义为 (x, y) 否则你会得到一个 IndexError

2D 索引必须像这样访问:

print(currentGrid[indices[:,0], indices[:,1]])

行索引和列索引将作为列表分别传递。

您的问题已经有一些很好的答案。这里只是针对您的特定代码的快速而肮脏的解决方案:

for i in indices:
    print(currentGrid[i[0],i[1]])

编辑:

如果您不想使用 for 循环,您需要执行以下操作:

假设您有 3 个 2D 矩阵值(维度 x1x2 您想要访问。这些值具有 "coordinates"(索引)V1(x11|x21), V2(x12|x22), V3(x13|x23)。然后,对于矩阵的每个维度(在您的情况下为 2),您需要创建一个列表,其中包含点的这一维度的索引。在本例中,您将创建一个包含 x1 的列表索引:[x11,x12,x13] 和一个包含 x2 点索引的列表:[x21,x22,x23]。然后将这些列表合并并将它们用作矩阵的索引:

indices = [[x11,x12,x13],[x21,x22,x23]]

或者你是怎么写的:

indices = list([(x11,x12,x13),(x21,x22,x23)])

现在使用您使用的点 ((0,0),(1,1),(2,0)) - 请注意您需要使用 (2,0) 而不是 (0,2),否则它会超出范围:

indices = list([(0,1,2),(0,1,0)])
print(currentGrid[indices])

这会给你 0, 0.9, 0.1。在此列表中,您可以根据需要应用 max() 命令(只是考虑您的整个问题):

maxValue = max(currentGrid[indices])

编辑2:

这里是一个示例,您可以如何将原始索引列表转换为正确的形状:

originalIndices = [(0,0),(1,1),(2,0)]

x1 = []
x2 = []

for i in originalIndices:
    x1.append(i[0])
    x2.append(i[1])

newIndices = [x1,x2]
print(currentGrid[newIndices])

编辑 3:

我不知道您是否可以使用循环将 max(x,0.5) 应用于 numpy 数组。但您可以改用 Pandas。您可以将列表转换为 pandas 系列,然后应用 lambda 函数:

import pandas as pd
maxValues = pd.Series(currentGrid[newIndices]).apply(lambda x: max(x,0.5))

这将为您提供一个包含 0.5,0.9,0.5 的 pandas 数组,您可以简单地将其转换回列表 maxValues = list(maxValues).

请注意:在后台,您总会有某种循环 运行,同样使用此命令。我怀疑,你会因此获得更好的表现。如果你真的想提高性能,然后使用 for 循环,连同 numba (you simply need to add a decorator to your function) and execute it in parallel. Or you can use the multiprocessing library and the Pool function, see here。只是给你一些启发。

编辑4:

我今天无意中看到了 this 页面,它允许使用 Numpy 做你想做的事。您的问题的解决方案(考虑来自我的 Edit2 的 newIndices 向量)是:

maxfunction = numpy.vectorize(lambda i: max(i,0.5))
print(maxfunction(currentGrid[newIndices]))