簡體   English   中英

numpy:逐元素減去數組

[英]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==0True==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的列向量來做同樣的事情,這顯然是一種更愚蠢的方法。)

最后一個快的想法:如果你的算法確實是“的布爾結果(任何元素ymx - y < a )為每個元素xm ”,你實際上並不需要“任何元素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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM