2 回答

TA貢獻1805條經驗 獲得超10個贊
盡管結果數組的大小都不同,但實際上有一個完全矢量化的解決方案。這個想法是這樣的:
對數組的所有元素及其坐標進行排序。
argsort
非常適合這種事情。在排序的數據中找到切點,這樣您就知道在哪里拆分數組,例如使用
diff
andflatnonzero
。split
沿著您找到的索引的坐標數組。如果您缺少元素,您可能需要根據每次運行的第一個元素生成一個密鑰。
這是一個帶您完成它的示例。假設您有一個d
size 的維數組n
。您的坐標將是一個(d, n)
數組:
d = arr.ndim n = arr.size
您可以直接生成坐標數組np.indices
:
coords = np.indices(arr.shape)
現在ravel
/reshape
將數據和坐標分別放入一個(n,)
和(d, n)
數組中:
arr = arr.ravel() # Ravel guarantees C-order no matter the source of the data coords = coords.reshape(d, n) # C-order by default as a result of `indices` too
現在對數據進行排序:
order = np.argsort(arr) arr = arr[order] coords = coords[:, order]
查找數據更改值的位置。您需要新值的索引,因此我們可以制作一個比實際第一個元素小 1 的假第一個元素。
change = np.diff(arr, prepend=arr[0] - 1)
位置的索引給出了數組中的斷點:
locs = np.flatnonzero(change)
您現在可以在這些位置拆分數據:
result = np.split(coords, locs[1:], axis=1)
您可以創建實際找到的值的鍵:
key = arr[locs]
如果您非常確信數組中存在所有值,那么您不需要密鑰。相反,您可以計算locs
as justnp.diff(arr)
和result
as just np.split(coords, inds, axis=1)
。
中的每個元素result
已經與where
/使用的索引一致nonzero
,但作為一個 numpy 數組。如果特別想要一個元組,您可以將其映射到一個元組:
result = [tuple(inds) for inds in result]
TL;博士
將所有這些組合成一個函數:
def find_locations(arr):
coords = np.indices(arr.shape).reshape(arr.ndim, arr.size)
arr = arr.ravel()
order = np.argsort(arr)
arr = arr[order]
coords = coords[:, order]
locs = np.flatnonzero(np.diff(arr, prepend=arr[0] - 1))
return arr[locs], np.split(coords, locs[1:], axis=1)
您可以通過將最后一行替換為缺少元素的空數組返回索引數組列表
result = [np.empty(0, dtype=int)] * 3000 # Empty array, so OK to use same reference
for i, j in enumerate(arr[locs]):
result[j] = coords[i]
return result
您可以選擇過濾您想要的特定范圍內的值(例如 0-2999)。

TA貢獻1890條經驗 獲得超9個贊
您可以在 numpy 中使用邏輯 OR 來一次傳遞所有這些相等條件,而不是一個一個地傳遞。
import numpy as np
conditions = False
for i in list:
conditions = np.logical_or(conditions,array3d == i)
newlist = np.where(conditions)
這允許 numpy 進行一次過濾,而不是分別為每個條件進行 n 次傳遞。
另一種更緊湊的方法
np.where(np.isin(array3d, list))
添加回答
舉報