3 回答

TA貢獻1856條經(jīng)驗 獲得超5個贊
我絕不是 Numpy 專家,但從我能找到的不同數(shù)組索引選項來看,這是我能找到的最快的解決方案:
bounds = np.array([[1,2], [1,3], [1,4]])
array = np.zeros((3,4))
for i, x in enumerate(bounds):
? ? cols = slice(x[0], x[1])?
? ? array[i, cols] = 1
在這里,我們遍歷邊界列表并使用切片引用列。
我嘗試了以下首先構建列索引列表和行索引列表的方法,但速度較慢。對于 10 000 x 10 000 陣列,在我的筆記本電腦上需要 10 秒加上 vir 0.04 秒。我猜這些切片有很大的不同。
bounds = np.array([[1,2], [1,3], [1,4]])
array = np.zeros((3,4))
cols = []
rows = []
for i, x in enumerate(bounds):
? ? cols += list(range(x[0], x[1]))?
? ? rows += (x[1] - x[0]) * [i]
# print(cols) [1, 1, 2, 1, 2, 3]
# print(rows) [0, 1, 1, 2, 2, 2]
array[rows, cols] = 1

TA貢獻1772條經(jīng)驗 獲得超5個贊
解決此問題的純 NumPy 方法的問題之一是,不存在使用軸上另一個數(shù)組的邊界來“切片”NumPy 數(shù)組的方法。因此,由此產(chǎn)生的擴展邊界最終變成了一個可變長度的列表列表,例如[[1],[1,2],[1,2,3]. 然后你可以使用np.eyeand np.sumover axis=0 來獲得所需的輸出。
bounds = np.array([[1,2], [1,3], [1,4]])
result = np.stack([np.sum(np.eye(4)[slice(*i)], axis=0) for i in bounds])
print(result)
array([[0., 1., 0., 0.],
[0., 1., 1., 0.],
[0., 1., 1., 1.]])
我嘗試了各種方法來將np.eye(4)from [start:stop] 切片到 NumPy 的開始和停止數(shù)組,但遺憾的是,您將需要迭代來完成此操作。
編輯:另一種可以在沒有任何循環(huán)的情況下以矢量化方式執(zhí)行此操作的方法是-
def f(b):
o = np.sum(np.eye(4)[b[0]:b[1]], axis=0)
return o
np.apply_along_axis(f, 1, bounds)
array([[0., 1., 0., 0.],
[0., 1., 1., 0.],
[0., 1., 1., 1.]])
編輯:如果您正在尋找一個超快的解決方案但可以容忍單個 for 循環(huán),那么根據(jù)我在該線程的所有答案中的模擬,最快的方法是-
def h(bounds):
zz = np.zeros((len(bounds), bounds.max()))
for z,b in zip(zz,bounds):
z[b[0]:b[1]]=1
return zz
h(bounds)
array([[0., 1., 0., 0.],
[0., 1., 1., 0.],
[0., 1., 1., 1.]])

TA貢獻1871條經(jīng)驗 獲得超13個贊
使用numba.njit裝飾器
import numpy as np
import numba
@numba.njit
def numba_assign_in_range(arr, bounds, val):
for i in range(len(bounds)):
s, e = bounds[i]
arr[i, s:e] = val
return arr
test_size = int(1e6) * 2
bounds = np.zeros((test_size, 2), dtype='int32')
bounds[:, 0] = 1
bounds[:, 1] = np.random.randint(0, 100, test_size)
a = np.zeros((test_size, 100))
和numba.njit
CPU times: user 3 μs, sys: 1 μs, total: 4 μs
Wall time: 6.2 μs
沒有numba.njit
CPU times: user 3.54 s, sys: 1.63 ms, total: 3.54 s
Wall time: 3.55 s
添加回答
舉報