【问题标题】:Apply custom function on numpy matrices在 numpy 矩阵上应用自定义函数
【发布时间】:2019-04-24 17:58:19
【问题描述】:

给定一个像 my_function(x,y) 这样的函数,它接受两个 ndarrays xy 作为输入并输出一个标量:

    def my_function(x,y):
        perm = np.take(x, y)
        return np.sum((np.power(2, perm) - 1) / (np.log2(np.arange(3, k + 3))))

我想找到一种方法将其应用于两个矩阵 r 和 p

    r = np.asarray([[5,6,7],[8,9,10]])
    p = np.asarray([[2,1,0],[0,2,1]])

以这样的方式返回一个带有值的ndarray

    np.asarray([my_function([5,6,7],[2,1,0]), my_function([8,9,10],[0,2,1])

【问题讨论】:

    标签: python numpy


    【解决方案1】:

    您可以稍微修改您的函数以使用take_along_axis 而不是take,这将允许您适应2D 解决方案。


    def my_function_2d(x, y, k=1):
        t = np.take_along_axis(x, y, -1)
        u = np.power(2, t) - 1
        v = np.log2(np.arange(3, k+3))
        return (u / v).sum(-1)
    
    my_function_2d(r, p, k=1)
    

    array([ 139.43547554, 1128.73332914])
    

    验证

    In [96]: k = 1
    
    In [97]: my_function([5,6,7],[2,1,0])
    Out[97]: 139.4354755392921
    
    In [98]: my_function([8,9,10],[0,2,1])
    Out[98]: 1128.7333291393375
    

    这同样适用于1D 案例:

    In [145]: my_function_2d(r[0], p[0], k=1)
    Out[145]: 139.4354755392921
    

    这种方法推广到N维的情况:

    In [157]: r = np.random.randint(1, 5, (2, 2, 2, 2, 2, 3))
    
    In [158]: p = np.random.randint(0, r.shape[-1], r.shape)
    
    In [159]: my_function_2d(r, p, k=3)
    Out[159]:
    array([[[[[ 8.34718483, 14.25597598],
              [12.25597598, 19.97868221]],
    
             [[12.97868221,  4.68481893],
              [ 2.42295943,  1.56160631]]],
    
    
            [[[23.42409467,  9.82346582],
              [10.93124418, 16.42409467]],
    
             [[23.42409467,  1.56160631],
              [ 3.68481893, 10.68481893]]]],
    
    
    
           [[[[15.97868221, 10.93124418],
              [ 5.40752517, 14.93124418]],
    
             [[ 4.14566566,  6.34718483],
              [14.93124418,  3.68481893]]],
    
    
            [[[ 9.20853795, 13.39462286],
              [23.42409467,  3.82346582]],
    
             [[23.42409467,  9.85293763],
              [ 4.56160631, 10.93124418]]]]])
    

    我假设您意识到您的方法不适用于所有输入和ks,有一些形状要求

    【讨论】:

      【解决方案2】:

      您可以尝试mapzip 的列表理解,如下所示。请注意,由于您没有指定k,我将k=1 用于运行代码

      def my_function(x,y):
          k=1
          perm = np.take(x, y)
          return np.sum((np.power(2, perm) - 1) / (np.log2(np.arange(3, k + 3))))
      
      
      r = np.asarray([[5,6,7],[8,9,10]])
      p = np.asarray([[2,1,0],[0,2,1]])
      
      result = np.asarray([my_function(i, j) for i, j in zip(r, p)])
      print (result)
      # [ 139.43547554 1128.73332914]
      

      【讨论】:

        【解决方案3】:

        您可以将np.vectorizesignature 关键字一起使用:

        k = 3
        np.vectorize(my_function, signature='(i),(i)->()')(r, p)
        
        # array([124.979052  , 892.46280834])
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-12-26
          • 2019-12-26
          • 2019-09-22
          • 1970-01-01
          • 2021-12-12
          • 1970-01-01
          • 2017-07-27
          • 2019-09-30
          相关资源
          最近更新 更多