2017-03-01 51 views
1

我有一個二維數組(它實際上是非常大的,另一個數組的視圖):NumPy的應用沿軸線和獲取行索引

x = np.array([[0, 1, 2], 
      [1, 2, 3], 
      [2, 3, 4], 
      [3, 4, 5]] 
     ) 

而且我有處理陣列的每一行的函數:

def some_func(a): 
    """ 
    Some function that does something funky with a row of numbers 
    """ 
    return [a[2], a[0]] # This is not so funky 

np.apply_along_axis(some_func, 1, x) 

我正在尋找一些方法來調用np.apply_along_axis功能,使我有機會獲得行索引(用於處理的行),然後能夠處理每行使用此功能:

def some_func(a, idx): 
    """ 
    I plan to use the index for some logic on which columns to 
    return. This is only an example 
    """ 
    return [idx, a[2], a[0]] # This is not so funky 
+0

射程陣列拉鍊呢? – Divakar

+0

@Divakar你能提供一個例子嗎?你可以假設二維數組是一個視圖,並且特別大,所以副本不是解決方案。 – slaw

回答

0

對於軸線= 1的2D陣列,apply_along_axis是一樣的陣列

In [149]: np.apply_along_axis(some_func, 1, x) 
Out[149]: 
array([[2, 0], 
     [3, 1], 
     [4, 2], 
     [5, 3]]) 
In [151]: np.array([some_func(i) for i in x]) 
Out[151]: 
array([[2, 0], 
     [3, 1], 
     [4, 2], 
     [5, 3]]) 

對於軸= 0,我們可以迭代上x.T的行的迭代。當數組爲3d時,apply_along_axis更有用,我們希望在除一個之外的所有維上進行迭代。然後它節省了一些乏味。但它不是速度解決方案。

隨着修改後的功能,我們可以使用標準的enumerate讓行和指標:

In [153]: np.array([some_func(v,i) for i,v in enumerate(x)]) 
Out[153]: 
array([[0, 2, 0], 
     [1, 3, 1], 
     [2, 4, 2], 
     [3, 5, 3]]) 

或用一個簡單的範圍迭代:

In [157]: np.array([some_func(x[i],i) for i in range(x.shape[0])]) 
Out[157]: 
array([[0, 2, 0], 
     [1, 3, 1], 
     [2, 4, 2], 
     [3, 5, 3]]) 

有用於獲取索引各種工具對於更高的尺寸,例如ndenumeratendindex

快速的解決方案 - 工作中的所有行一次:

In [158]: np.column_stack((np.arange(4), x[:,2], x[:,0])) 
Out[158]: 
array([[0, 2, 0], 
     [1, 3, 1], 
     [2, 4, 2], 
     [3, 5, 3]]) 
+0

很高興知道。我有義務問,但有沒有一種方法是速度解決方案? – slaw

+0

我添加了一個完整的數組解決方案 – hpaulj

0

這裏有一個替代的解決方案,在等待真正的功能得到了實現。 這會有點不整齊。但是,也許足以解決您目前的問題。 :)

# create global variable 
In [247]: global counter 

# Initialize it to your need 
In [248]: counter = 0 

# create your function callback, lambda also could be used 
In [252]: def funct(row): 
    ...:  # reference to global variable created before hand 
    ...:  global counter 
    ...:  counter += 1 # increment the counter 
    ...:  # return something, or else 
    ...:  # will raise a 'NoneType' has no len() exception 
    ...:  return counter 

In [260]: np.apply_along_axis(funct, 1, np.array([[0],[0],[0]])) 
Out[260]: array([1, 2, 3]) 

# revert counter to initial state or the counter will keep raising afterward 
In [261]: counter = 0 

# or you could just delete it if you had no use for it anymore 
In [262]: del counter 

希望,可能是一些幫助你:)