亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

以矢量化方式查找不同元素的索引

以矢量化方式查找不同元素的索引

狐的傳說 2022-10-18 16:03:03
我有一個ints的列表a,介于 0 到 3000 之間len(a) = 3000。我有一個for循環遍歷這個列表,在更大的數組中搜索每個元素的索引。import numpy as npa = [i for i in range(3000)]array = np.random.randint(0, 3000, size(12, 1000, 1000))newlist = []for i in range(0, len(a)):    coord = np.where(array == list[i])    newlist.append(coord)如您所見,coord3D 矩陣中的值等于列表中的值的坐標 x、y、z 的 3 個數組。for有沒有辦法在沒有循環的情況下以矢量化方式做到這一點?輸出應該是一個元組列表,每個元素對應一個a:# each coord looks like this:print(coord)(array[1, ..., 1000], array[2, ..., 1000], array[2, ..., 12])# combined over all the iterations:print(newlist)[coord1, coord2, ..., coord3000]
查看完整描述

2 回答

?
holdtom

TA貢獻1805條經驗 獲得超10個贊

盡管結果數組的大小都不同,但實際上有一個完全矢量化的解決方案。這個想法是這樣的:

  1. 對數組的所有元素及其坐標進行排序。argsort非常適合這種事情。

  2. 在排序的數據中找到切點,這樣您就知道在哪里拆分數組,例如使用diffand flatnonzero

  3. split沿著您找到的索引的坐標數組。如果您缺少元素,您可能需要根據每次運行的第一個元素生成一個密鑰。

這是一個帶您完成它的示例。假設您有一個dsize 的維數組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]

如果您非常確信數組中存在所有值,那么您不需要密鑰。相反,您可以計算locsas justnp.diff(arr)resultas 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)。


查看完整回答
反對 回復 2022-10-18
?
當年話下

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))


查看完整回答
反對 回復 2022-10-18
  • 2 回答
  • 0 關注
  • 153 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號