[英]How can I assign values from one array to another according to the index more efficiently?
我試圖根據源數組中有多少個數組來替換一個數組的值。 我根據總和從替換數組中的給定索引中分配一個值。 因此,如果連續有 2 個,則為物種分配值l1[1]
,如果有一個單元,則為輸出分配值l1[0]
。
在一個具體的例子中會更好地看到:
import numpy as np
l1 = np.array([4, 5])
x112 = np.array([[0, 0], [0, 1], [1, 1], [0, 0], [1, 0], [1, 1]])
array([[0, 0],
[1, 0],
[1, 1],
[0, 0],
[1, 0],
[1, 1]])
所需輸出:
[[0]
[4]
[5]
[0]
[4]
[5]]
我通過計算每行中的單位並使用np.where
進行np.where
分配來np.where
:
x1x2 = np.array([0, 1, 2, 0 1, 2]) #count value 1
x1x2 = np.where(x1x2 != 1, x1x2, l1[0])
x1x2 = np.where(x1x2 != 2, x1x2, l1[1])
print(x1x2)
輸出
[0 4 5 0 4 5]
這可以更有效地完成嗎?
好吧,我實際上嘗試了對您的代碼進行去向量化。 首先是您擁有的矢量化 NumPy:
def op(x112, l1):
# bit of cheating, adding instead of counting 1s
x1x2 = x112[:,0] + x112[:,1]
x1x2=np.where(x1x2 != 1, x1x2, l1[0])
x1x2=np.where(x1x2 != 2, x1x2, l1[1])
return x1x2
最有效的替代方法是只循環一次x112
,所以讓我們做一個 Numba 循環。
import numba as nb
@nb.njit
def loop(x112, l1):
d0, d1 = x112.shape
x1x2 = np.zeros(d0, dtype = x112.dtype)
for i in range(d0):
# actually count the 1s
num1s = 0
for j in range(d1):
if x112[i,j] == 1:
num1s += 1
if num1s == 1:
x1x2[i] = l1[0]
elif num1s == 2:
x1x2[i] = l1[1]
return x1x2
Numba 循環在我的筆記本電腦上有大約 9-10 倍的速度提升。
%timeit op(x112, l1)
8.05 µs ± 34.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit loop(x112, l1)
873 ns ± 5.09 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
正如@Mad_Physicist 所要求的那樣,使用更大的數組進行計時。 我也包括他的高級索引方法。
x112 = np.random.randint(0, 2, size = (100000, 2))
l1_v2 = np.array([0,4,5])
%timeit op(x112, l1)
1.35 ms ± 27.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit loop(x112, l1)
956 µs ± 2.78 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit l1_v2[x112.sum(1)]
1.2 ms ± 1.05 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
編輯:好吧,也許對這些時間持保留op(x112, l1)
因為當我重新啟動 IPython 內核並重新運行這些東西時, op(x112, l1)
提高到390 µs ± 22.1 µs per loop
而其他方法保持相同的性能( 971 微秒,1.23 毫秒)。
您可以使用直接索引:
l1 = np.array([0, 4, 5])
x112 = np.array([[0, 0], [0, 1], [1, 1], [0, 0], [1, 0], [1, 1]])
result = l1[x112.sum(1)]
如果您可以在創建時l1
在l1
前面加上零,則此方法有效。 如果不:
result = np.r_[0, l1][x112.sum(1)]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.