2016-07-19 51 views
0

我有一個2d座標數組,我想找到與給定座標匹配的條目索引。匹配二維數組中的座標的有效方法

例如,我的數組可能是A

A = [[[1.5, 2.0], [1.0, 2.3], [5.4, 2.3]], 
    [[3.2, 4.4], [2.0, 3.1], [0.0, 2.3]], 
    [[1.0, 2.0], [2.3, 3.4], [4.0, 1.1]]] 

和座標我想匹配是x = [1.0, 2.0]。我想獲得座標[1.0, 2.0]的索引,這將是(2, 0)

目前,我做如下:

matching_inds = [(i, j) for i in xrange(len(A)) for j in xrange(len(A[0])) if A[i,j][0] == x[0] and A[i,j][1] == x[1]] 

這工作,但我覺得應該有一些更有效的(我的工作陣列大得多)。

我試過np.where()但是對於更高維度來說這似乎不起作用。它將返回所有x座標匹配的座標索引,而不是x和y座標。

任何提示將不勝感激。

+1

儘管你有一個3D數組......你的列表清單包含更多列表。 –

+0

嚴格來說,我想你是對的。我將最裏面的列表視爲一個元組,但我知道Python將它視爲當前形式的列表。 – berkelem

+0

一個點能否在數組中出現多次?如果是這樣,如果您的搜索在多個地方匹配,您希望得到什麼答案? – alexis

回答

2

你可以使用你的代碼稍微簡單的版本:

In [115]: A = [[[1.5, 2.0], [1.0, 2.3], [5.4, 2.3]], 
    ...:  [[3.2, 4.4], [2.0, 3.1], [0.0, 2.3]], 
    ...:  [[1.0, 2.0], [2.3, 3.4], [4.0, 1.1]]] 

In [116]: x = [1., 2.] 

In [117]: [(i, j) for i, row in enumerate(A) for j, coor in enumerate(row) if coor == x] 
Out[117]: [(2, 0)] 

但是,如果陣列很大,你最好使用量化方法:

In [118]: import numpy as np 

In [119]: arr = np.array(A) 

In [120]: np.argwhere(np.logical_and(arr[:,:,0] == x[0], arr[:,:,1] == x[1])) 
Out[120]: array([[2, 0]], dtype=int64) 

編輯:的高效和優雅的方式着手完成將工作:

In [158]: np.argwhere(np.all(arr == x, axis=2)) 
Out[158]: array([[2, 0]], dtype=int64) 
+0

謝謝!那些numpy命令非常有用! – berkelem

+0

我對原始文件('np.logical_and()')進行編輯後的版本('np.all()'),發現'np.logical_and()'比np.all()快4倍「 '。 – berkelem

+0

有趣...感謝您的反饋!無論如何,如果要匹配三維座標而不是二維座標,那麼依賴於'np.all()'的方法可以很好地工作,而您應該調整基於np.logical_and()的代碼讓它起作用。 – Tonechas

1

你可能可以試試這個:

import numpy as np 
arrA = np.array(A) 
x = [1.0, 2.0] 

np.where((arrA == x).sum(axis = 2) == 2) 
# (array([2]), array([0])) 
1

如果你會做很多的查找,您可以建立一個索引映射的座標位置在你的矩陣。例如,(1.5, 2.0)映射到(0,0)(1.0, 2.3)映射到(0, 1),等這裏的如何建立你的數組的索引:

>>> A = [[[1.5, 2.0],[1.0, 2.3],[5.4, 2.3]], 
...  [[3.2, 4.4],[2.0, 3.1],[0.0, 2.3]], 
...  [[1.0, 2.0],[2.3, 3.4],[4.0, 1.1]]] 
>>> revind = dict() 
>>> for r, row in enumerate(A): 
...  for c, pt in enumerate(row): 
...   revind[tuple(pt)] = (r, c) 
... 
>>> revind[(1.0, 2.0)] 
(2,0) 

或者作爲(不易閱讀)理解:

>>> revind = dict((tuple(pt), (r,c)) for r,row in enumerate(A) for c,pt in enumerate(row)) 

請注意,您必須使用元組,因爲列表是「可變的」,不能用作字典鍵。這樣做可以確保每次查詢都在O(1)時間內進行,這比搜索一個長列表要快得多(就像在你的問題和接受的答案中一樣)。

+0

感謝您的建議。我只需要爲每個大型數組找到一個座標,因此對於我的目的,單個搜索比創建字典更有效。 – berkelem

相關問題