[英]Numpy: Subtract array element by element
標題可能含糊不清,不知道該怎么寫。
我使用numpy和matplotlib在python中使用粒子模擬器取得了一些進展,我設法實現了coloumb,重力和風,現在我只想增加溫度和壓力,但是我有一個預優化問題(萬惡之源) )。 我想看看粒子何時崩潰:
問:基於布爾條件,是否有可能將數組的差值與自己的每個元素取值? 我想避免循環。
例如: (x - any element in x) < a
應該返回類似
[True, True, False, True]
如果x中的元素0,1和3滿足條件。
編輯:
等效的循環為:
for i in len(x):
for j in in len(x):
#!= not so important
##earlier question I asked lets me figure that one out
if i!=j:
if x[j] - x[i] < a:
True
我發現numpy操作比測試要快得多,這幫助我大大加快了工作速度。
如果有人想玩,這里是一個示例代碼。
#Simple circular box simulator, part of part_sim
#Restructure to import into gravity() or coloumb () or wind() or pressure()
#Or to use all forces: sim_full()
#Note: Implement crashing as backbone to all forces
import numpy as np
import matplotlib.pyplot as plt
N = 1000 #Number of particles
R = 8000 #Radius of box
r = np.random.randint(0,R/2,2*N).reshape(N,2)
v = np.random.randint(-200,200,r.shape)
v_limit = 10000 #Speedlimit
plt.ion()
line, = plt.plot([],'o')
plt.axis([-10000,10000,-10000,10000])
while True:
r_hit = np.sqrt(np.sum(r**2,axis=1))>R #Who let the dogs out, who, who?
r_nhit = ~r_hit
N_rhit = r_hit[r_hit].shape[0]
r[r_hit] = r[r_hit] - 0.1*v[r_hit] #Get the dogs back inside
r[r_nhit] = r[r_nhit] +0.1*v[r_nhit]
#Dogs should turn tail before they crash!
#---
#---crash code here....
#---crash end
#---
vmin, vmax = np.min(v), np.max(v)
#Give the particles a random kick when they hit the wall
v[r_hit] = -v[r_hit] + np.random.randint(vmin, vmax, (N_rhit,2))
#Slow down honey
v_abs = np.abs(v) > v_limit
#Hit the wall at too high v honey? You are getting a speed reduction
v[v_abs] *=0.5
line.set_ydata(r[:,1])
line.set_xdata(r[:,0])
plt.draw()
我計划一旦弄清楚如何...就可以在上面的數據點添加顏色,以便可以在較大的框中輕松區分高速粒子。
例如:x-x <a中的任何元素應返回類似
[正確,正確,錯誤,正確]
如果x中的元素0,1和3滿足條件。 我發現numpy操作比測試要快得多,這幫助我大大加快了工作速度。
是的,只有m < a
。 例如:
>>> m = np.array((1, 3, 10, 5))
>>> a = 6
>>> m2 = m < a
>>> m2
array([ True, True, False, True], dtype=bool)
現在,問題來了:
問:基於布爾條件,是否有可能將數組的差值與自己的每個元素取值? 我想避免循環。
我不確定您在這里要什么,但似乎與下面的示例不匹配。 您是否要例如從滿足謂詞的每個元素中減去1? 在那種情況下,您可以依靠False==0
和True==1
的事實,然后減去布爾數組:
>>> m3 = m - m2
>>> m3
>>> array([ 0, 2, 10, 4])
根據您的澄清,您希望獲得與此偽代碼循環等效的代碼:
for i in len(x):
for j in in len(x):
#!= not so important
##earlier question I asked lets me figure that one out
if i!=j:
if x[j] - x[i] < a:
True
我認為這里的困惑與您所說的完全相反:您不希望“基於布爾條件的數組與每個元素的差異”,而是“基於差異的布爾條件”具有自己的每個元素的數組的結果”。 即使這樣,也只能真正得到len(m)* len(m)布爾型的平方矩陣,但是我認為剩下的部分是“ any”。
無論如何,您都需要一個隱式笛卡爾積,將m的每個元素與m的每個元素進行比較。
您可以輕松地將其從兩個循環減少到一個(或者,隱式向量化其中一個循環,從而獲得通常的numpy性能優勢)。 對於每個值,通過從每個元素減去該值並將結果與a
進行比較,創建一個新數組,然后將它們合起來:
>>> a = -2
>>> comparisons = np.array([m - x < a for x in m])
>>> flattened = np.any(comparisons, 0)
>>> flattened
array([ True, True, False, True], dtype=bool)
但是您也可以輕松地將其轉換為簡單的矩陣運算。 減去的每一個元素m
距離的所有其他元素m
只是m - mT
。 (您可以使乘積更明確,但是numpy
不需要添加行向量和列向量。)然后,您只需將其每個元素與標量a
進行比較,並用any
歸約,就可以了。完成:
>>> a = -2
>>> m = np.matrix((1, 3, 10, 5))
>>> subtractions = m - m.T
>>> subtractions
matrix([[ 0, 2, 9, 4],
[-2, 0, 7, 2],
[-9, -7, 0, -5],
[-4, -2, 5, 0]])
>>> comparisons = subtractions < a
>>> comparisons
matrix([[False, False, False, False],
[False, False, False, False],
[ True, True, False, True],
[ True, False, False, False]], dtype=bool)
>>> np.any(comparisons, 0)
matrix([[ True, True, False, True]], dtype=bool)
或者,將它們全部放在一行中:
>>> np.any((m - m.T) < a, 0)
matrix([[ True, True, True, True]], dtype=bool)
如果您需要m
是數組而不是矩陣,則可以用m - np.matrix(m).T
代替減法線。
對於更高的維度,實際上需要在數組中工作,因為您要嘗試對自己的2D數組進行笛卡爾乘積以得到4D數組,而numpy
卻不做4D矩陣。 因此,您不能使用簡單的“行向量-列向量=矩陣”技巧。 但是您可以手動執行以下操作:
>>> m = np.array([[1,2], [3,4]]) # 2x2
>>> m4d = m.reshape(1, 1, 2, 2) # 1x1x2x2
>>> m4d
array([[[[1, 2],
[3, 4]]]])
>>> mt4d = m4d.T # 2x2x1x1
>>> mt4d
array([[[[1]],
[[3]]],
[[[2]],
[[4]]]])
>>> subtractions = m - mt4d # 2x2x2x2
>>> subtractions
array([[[[ 0, 1],
[ 2, 3]],
[[-2, -1],
[ 0, 1]]],
[[[-1, 0],
[ 1, 2]],
[[-3, -2],
[-1, 0]]]])
從那里開始,其余部分與以前相同。 將其組合成一行:
>>> np.any((m - m.reshape(1, 1, 2, 2).T) < a, 0)
(如果您還記得我的原始答案,我在reshape
會不知所措,並且通過將m
乘以1s的列向量來做同樣的事情,這顯然是一種更愚蠢的方法。)
最后一個快的想法:如果你的算法確實是“的布爾結果(任何元素y
的m
, x - y < a
)為每個元素x
的m
”,你實際上並不需要“任何元素y
”您可以只使用“用於最大元素y
”。 因此,您可以將O(N ^ 2)簡化為O(N):
>>> (m - m.max()) < a
或者,如果a
為正,則始終為false,因此可以簡化為O(1):
>>> np.zeros(m.shape, dtype=bool)
但是我猜測您的實際算法實際上是使用abs(x - y)
或更復雜的東西,無法通過這種方式進行簡化。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.