【问题标题】:Numpy Apply Along Axis and Get Row IndexNumpy沿轴应用并获取行索引
【发布时间】:2017-03-01 20:21:21
【问题描述】:

我有一个 2D 数组(它实际上非常大并且是另一个数组的视图):

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

【问题讨论】:

  • 用范围数组压缩它?
  • @Divakar 你能举个例子吗?您可以假设 2D 数组是一个视图并且非常大,因此副本不是解决方案。
  • 嗨,这个问题你解决了吗?
  • @slaw 这仍然是一个非首发!?疯狂

标签: python numpy


【解决方案1】:

对于轴=1 的二维数组,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]])

对于axis=0,我们可以迭代x.Tapply_along_axis 在数组是 3d 时更有用,并且我们想要迭代除一维之外的所有维度。然后它节省了一些乏味。但这不是一个速度解决方案。

通过您修改后的函数,我们可以使用标准的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]])

【讨论】:

  • 很高兴知道。我有义务问,但有没有一种速度解决方案的方法?
  • 我添加了一个全阵列解决方案
  • 嗨,np.apply_along_axis(some_func, 1, x) some_func 是什么
  • @going,见问题帖。
【解决方案2】:

我遇到了 3 维张量的问题,所以我认为值得发布一个泛化的解决方案,即使用 np.ndenumerate

    f = lambda indices: #(whatever you'd like to do)

    output = np.empty(M.shape)
    for i, x in np.ndenumerate(M):
        output(i) = f(i)

【讨论】:

    【解决方案3】:

    这是一个替代解决方案,等待真正的功能实现。 这会有点不整洁。但也许足以解决您目前的问题。 :)

    # 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 
    

    希望对你有所帮助:)

    【讨论】:

    • 真的没有办法按照OP想要的方式访问行/列索引吗!?
    猜你喜欢
    • 2021-07-29
    • 2021-07-20
    • 2017-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-25
    相关资源
    最近更新 更多