2014-05-05 16 views
10

我想將一個採用二維數組(並返回一個相同形狀)的函數應用於3D數組的每個2D切片。什麼是這樣做的有效方式? numpy.fromiter返回一維數組,numpy.fromfunction需要分別應用於每個座標。將函數應用於3D numpy數組的每個2D切片的有效方法

目前我做

foo = np.array([func(arg, bar2D) for bar2D in bar3D]) 

這給我我想要的,但名單理解是很慢的。另外,func是具有特定邊界條件的一維導數。 numpy.gradient似乎只能做N維導數,而N是數組的維數,但是也許還有另外一個例程會爲我完成整個事情?

編輯:列表理解工作,但我正在尋找一個更快的方式來做到這一點。 bar3D可以很大,最大爲(500,500,1000)。我發現將數組函數應用於數組的所有numpy例程似乎都假定函數或數組都是1D。

回答

-1

假設你有一個數組,一:

>>> a=np.random.random((4,3,2)) 

array([[[ 0.27252091, 0.78545835], 
     [ 0.83604934, 0.48509821], 
     [ 0.77828735, 0.26630055]], 

     [[ 0.98623474, 0.29839813], 
     [ 0.15893604, 0.61870988], 
     [ 0.62281607, 0.27193647]], 

     [[ 0.47976331, 0.2471835 ], 
     [ 0.77323041, 0.30137068], 
     [ 0.52906156, 0.53950597]], 

     [[ 0.59207654, 0.86355457], 
     [ 0.50250812, 0.75688653], 
     [ 0.91046136, 0.5785383 ]]]) 

您可以訪問2D片,像這樣:

>>> for x in range(a.shape[0]): 
     print a[x,:,:] 

>>> for x in range(a.shape[1]): 
     print a[:,x,:] 

>>> for x in range(a.shape[2]): 
     print a[:,:,x] 
+0

對不起,這不是我所追求的。我知道如何切片(bar2D中的bar2D給我每個2D切片)。我想要做的是對每個2D切片應用一個函數,並從中創建一個新的數組。 – Yossarian

+0

你可以創建另一個與'a'形狀相同的數組,例如'b',然後代替'print a [x,:,]',做'b [x,:,] = yourfunc (一[X,:,:])'。 – atomh33ls

+0

這相當於我目前正在做的事情。實際上,它比列表理解還要慢。我正在尋求一種有效的方法來爲大型3D陣列做到這一點。 – Yossarian

1

我不知道的應用功能的ND切片任何通用的方法陣列。但有兩種方法可以解決這個問題。

如果你想要做的是在每個二維切片的每一行或列應用一維導數,這相當於應用衍生到各個1D切片,並且可以使用np.apply_along_axis:

values = np.arange(4)*np.arange(3)[:, None]+np.arange(2)[:, None, None]*2 
>>> array([[[0, 0, 0, 0], 
      [0, 1, 2, 3], 
      [0, 2, 4, 6]], 

     [[2, 2, 2, 2], 
     [2, 3, 4, 5], 
     [2, 4, 6, 8]]]) 

np.apply_along_axis(np.gradient, 2, values) 
>>> array([[[ 0., 0., 0., 0.], 
      [ 1., 1., 1., 1.], 
      [ 2., 2., 2., 2.]], 

      [[ 0., 0., 0., 0.], 
      [ 1., 1., 1., 1.], 
      [ 2., 2., 2., 2.]]]) 

這區分了每個2D切片的行。要區分每列,請執行以下操作:np.apply_along_axis(np.gradient, 2, values)

如果要執行需要兩個維度的操作,通常可以通過廣播和軸參數獲取。例如如果你想V[i, j] = sqrt((V[i,j]-V[i, j-1])^2+V[i, j]-V[i-1, j])^2每個切片V你可以這樣做:

xdiffs = np.zeros_like(values) 
xdiffs[:, 1:, :]= np.diff(values, axis=1) 

ydiffs = np.zeros_like(values) 
ydiffs[:, :, 1:] = np.diff(values, axis=2) 

diffnorms = np.linalg.norm(xdiffs, ydiffs) 

>>> array(
    [[[ 0.  , 0.  , 0.  , 0.  ], 
    [ 0.  , 1.41421356, 2.23606798, 3.16227766], 
    [ 0.  , 2.23606798, 2.82842712, 3.60555128]], 

    [[ 0.  , 0.  , 0.  , 0.  ], 
    [ 0.  , 1.41421356, 2.23606798, 3.16227766], 
    [ 0.  , 2.23606798, 2.82842712, 3.60555128]]]) 

這是一個有點麻煩,以獲得正確的尺寸,但它通常將是最有效的解決方案。

這個例子在邊界處使用零,如果你需要別的東西,你需要設置normdiff[:, :, 0]normdiff[:, 0, :]到正確的邊界值。

相關問題