通过 Python 中的索引列表访问矩阵的元素以将 max(val, 0.5) 应用于每个值,而无需 for 循环

Zhe*_*ell 5 python arrays matrix indices python-3.x

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

test = numpy.array([1,2,3,4,5,6])
indices = list([1,3,5])
print(test[indices])
Run Code Online (Sandbox Code Playgroud)

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

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

currentGrid = numpy.array(  [[0,   0.1],
                             [0.9, 0.9],
                             [0.1, 0.1]])
indices = list([(0,0),(1,1)])
print(currentGrid[indices])
Run Code Online (Sandbox Code Playgroud)

这应该为我显示“[0.0 0.9]”,表示矩阵中 (0,0) 处的值和 (1,1) 处的值。而是显示“[ 0.1 0.1]”。此外,如果我尝试使用 3 个索引:

indices = list([(0,0),(1,1),(0,2)])
Run Code Online (Sandbox Code Playgroud)

我现在收到以下错误:

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

我最终需要对这些索引处的所有元素应用一个简单的 max() 操作,并且需要以最快的方式来实现优化。

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

Wur*_*pQX 2

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

for i in indices:
    print(currentGrid[i[0],i[1]])
Run Code Online (Sandbox Code Playgroud)

编辑:

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

假设您的 2D 矩阵有 3 个值(具有维度x1x2您想要访问的值。这些值具有“坐标”(索引)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]]
Run Code Online (Sandbox Code Playgroud)

或者你怎么写:

indices = list([(x11,x12,x13),(x21,x22,x23)])
Run Code Online (Sandbox Code Playgroud)

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

indices = list([(0,1,2),(0,1,0)])
print(currentGrid[indices])
Run Code Online (Sandbox Code Playgroud)

这会给你0, 0.9, 0.1。在此列表中,如果您愿意,您可以应用 max() 命令(只是为了考虑您的整个问题):

maxValue = max(currentGrid[indices])
Run Code Online (Sandbox Code Playgroud)

编辑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])
Run Code Online (Sandbox Code Playgroud)

编辑3:

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

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

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

请注意:在后台,您将始终运行某种循环,也使用此命令。我怀疑,这样你会获得更好的表现。如果您确实想提高性能,请使用 for 循环和numba(您只需向函数添加装饰器)并并行执行它。或者您可以使用multiprocessing库和Pool函数,请参阅此处。只是为了给你一些启发。

编辑4:

我今天无意中看到了这个页面,它允许您完全按照您的意愿进行操作Numpy。您的问题的解决方案(考虑newIndices来自我的 Edit2 的向量)是:

maxfunction = numpy.vectorize(lambda i: max(i,0.5))
print(maxfunction(currentGrid[newIndices]))
Run Code Online (Sandbox Code Playgroud)