我有 3 個陣列,x,y和q. 陣列x和y具有相同長度的,q是一個查詢陣列。假設x和中的所有值q都是唯一的。對于 的每個值q,我想在 中找到對應值的索引x。然后我想在y. 如果 fromq中沒有出現值x,我想回傳np.nan。
作為一個具體示例,請考慮以下陣列:
x = np.array([1, 2, 3])
y = np.array([4, 5, 6])
q = np.array([2, 0])
因為只有值 2 出現在 中x,所以正確的回傳值是:
out = np.array([5, np.nan])
使用 for 回圈,可以這樣做:
out = []
for i in range(len(q)):
for j in range(len(x)):
if np.allclose(q[i], x[j]):
out.append(y[j])
break
else:
out.append(np.nan)
output = np.array(out)
顯然,這是相當緩慢的。有沒有更簡單的方法可以使用 numpy 內置函式來做到這一點np.argwhere?或者使用熊貓會更容易嗎?
uj5u.com熱心網友回復:
Numpy 廣播應該可以作業。
# a mask that flags any matches
m = q == x[:, None]
# replace any value in q without any match in x by np.nan
res = np.where(m.any(0), y[:, None] * m, np.nan).sum(0)
res
# array([ 5., nan])
我應該注意,這僅x在沒有重復項的情況下才有效。
因為它依賴于構建len(x) x len(q)陣列,如果q很大,上面的解決方案會遇到記憶體問題。在這種情況下,另一個 pandas 解決方案將更有效地作業:
# map q to y via x
res = pd.Series(q).map(pd.Series(y, index=x)).values
uj5u.com熱心網友回復:
我認為您可以在一行中解決此問題,但使用一行和一些廣播:
out = [y[bl].item() if bl.any() else None for bl in x[None,:]==q[:,None] ]
在我看來,這是一個優雅的解決方案,但讀起來有點混亂。我會一步一步去。
x[None,:]==q[:,None]將 q 中的每個值與 x 中的每個值進行比較并回傳(len(q),len(x)布爾陣列(在這種情況下為[[False,True,False], [False,False,False]]- 您可以使用具有相同長度的布爾陣列對 y 進行索引
len(y)。所以你可以呼叫y[ [False,True,False] ]來獲取 y[1] 的值。 - 如果 bool 陣列包含所有 false 那么你必須放一個
None所以這就是為什么使用if-else
uj5u.com熱心網友回復:
這里也是如何使用np.argwhere。使用更舒適的 Pandas 或 numpy。
out_idx = [y[np.argwhere(x==value).reshape(-1)] for value in q]
out = [x[0] if len(x) else np.nan for x in out_idx]
uj5u.com熱心網友回復:
這是一種解決您的問題的方法:
query_results = pd.DataFrame(index=q).join(pd.DataFrame({'y':y}, index=x)).T.to_numpy()[0]
輸出:
[ 5. nan]
uj5u.com熱心網友回復:
如果性能是這個問題的主要目標,您可以使用 numba 庫和 jitting 加速回圈代碼,這將非常快:
x = np.random.permutation(2000)[:1100]
y = np.random.permutation(2000)[:1100]
q = np.random.permutation(3000)[:500]
print((q > 2000).sum())
@nb.njit
def numba_(x, y, q):
out = []
for i in range(len(q)):
for j in range(len(x)):
if q[i] == x[j]:
out.append(y[j])
break
else:
out.append(np.nan)
return np.array(out)
或并行模式:
@nb.njit(parallel=True)
def numba_p(x, y, q):
out = np.empty(q.shape[0])
out.fill(np.nan)
for i in nb.prange(q.shape[0]):
for j in range(x.shape[0]):
if q[i] == x[j]:
out[i] = y[j]
break
return out
在大型陣列上,它比非機器人答案 ( np.where)和constantstranger答案快得多,并且對于非機器人答案 (Pandas)幾乎相同:
100 loops, best of 5: 4.4 ms per loop <-- not a robot (np.where)
100 loops, best of 5: 337 μs per loop <-- not a robot (Pandas)
100 loops, best of 5: 350 μs per loop <-- numba
100 loops, best of 5: 341 μs per loop <-- numba_p
100 loops, best of 5: 2.18 ms per loop <-- constantstranger (Pandas)
注意:在新版本中將在性能方面得到很大改進np.where,這可以幫助非機器人答案在更大的陣列上擊敗常量陌生人答案。
更新: 在我對更大陣列的新測驗中,不是機器人答案(熊貓)要快得多(最快)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/494400.html
