我知道如何通过索引来访问向量中的元素:
test = numpy.array([1,2,3,4,5,6])
indices = list([1,3,5])
print(test[indices])
给出正确答案:[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])
对于(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()操作,并且需要以最快的方式进行优化。
我究竟做错了什么 ?如何以非常有效的方式访问矩阵中的特定元素以对它们执行某些操作(不使用列表推导也不使用循环)。
你的问题已经有了很好的答案。这里只是您特定代码的快速而肮脏的解决方案:
for i in indices:
print(currentGrid[i[0],i[1]])
如果您不想使用for循环,则需要执行以下操作:
假设你有2个2D矩阵的值(你想要访问的尺寸为x1
和x2
。这些值有“坐标”(索引)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])
这里有一个示例如何转换原始索引列表以使其成为正确的形状:
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])
我不知道你是否可以使用循环将max(x,0.5)
应用于numpy数组。但你可以改用熊猫。您可以将列表转换为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(你只需要在你的函数中添加一个装饰器)并并行执行它。或者您可以使用multiprocessing
库和Pool
函数,请参阅here。只是为了给你一些灵感。
无意中我今天看到了this页面,它允许用Numpy
做你想要的。解决问题(从我的Edit2中考虑newIndices
向量)到你的问题是:
maxfunction = numpy.vectorize(lambda i: max(i,0.5))
print(maxfunction(currentGrid[newIndices]))
问题是你传递给数组的索引的排列。如果你的数组是二维的,你的索引必须是两个列表,一个包含垂直索引,另一个包含水平索引。例如:
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]])
行索引和列索引将作为列表单独传递。