【问题标题】:How to use numpy functions to make this list如何使用 numpy 函数制作此列表
【发布时间】:2019-09-12 22:28:03
【问题描述】:

我正在尝试加快此列表的理解速度,我尝试使用 numpy.vectorize,但无法使其工作。是否可以使用该功能,如果可以,如何或有另一种方法可以使其更快?列表“a”是一个 numpy ndarray(二维),所以我知道为了让它更快,你应该使用 numpy 函数而不是列表推导,但是找不到如何使用这些函数。

[[[255,255,255] if y else [0,0,0] for y in row ] for row in a]

【问题讨论】:

  • 你用它做什么?可以只使用 NumPy 进行广播吗?您能否举例说明您对list 使用的值是多少?顺便说一句,您不应该使用 list 作为变量。
  • 你想要的输出是什么?
  • @AviThour 仅仅因为它具有相似的标题并不能使问题相同。链接问题的答案在这里无济于事。

标签: python python-3.x performance numpy list-comprehension


【解决方案1】:

在尝试了更多的东西后,我发现了这个 oneliner,它可以完成工作并且速度也很快。

    np.where(a != 0, 0, 255).repeat(3, 1).reshape(len(a), len(a[0]), 3)

【讨论】:

    【解决方案2】:

    看起来您的列表将类似于:

    In [22]: alist = [[0,1,2],[3,0,0]]                                              
    

    以及你理解的结果:

    In [23]: [[[255,255,255] if y else [0,0,0] for y in row] for row in alist]      
    Out[23]: 
    [[[0, 0, 0], [255, 255, 255], [255, 255, 255]],
     [[255, 255, 255], [0, 0, 0], [0, 0, 0]]]
    

    要在numpy 中做类似的事情,请创建一个数组(子列表必须具有相同的长度):

    In [24]: arr = np.array(alist)                                                  
    In [25]: arr                                                                    
    Out[25]: 
    array([[0, 1, 2],
           [3, 0, 0]])
    

    制作一个目标数组 - 3d 形状:

    In [27]: res = np.zeros(arr.shape+(3,),int)                                     
    In [28]: res                                                                    
    Out[28]: 
    array([[[0, 0, 0],
            [0, 0, 0],
            [0, 0, 0]],
    
           [[0, 0, 0],
            [0, 0, 0],
            [0, 0, 0]]])
    

    y 不为 0 的掩码:

    In [29]: mask = arr!=0                                                          
    In [30]: mask                                                                   
    Out[30]: 
    array([[False,  True,  True],
           [ True, False, False]])
    

    这个掩码会选择res的3个元素:

    In [31]: res[mask]                                                              
    Out[31]: 
    array([[0, 0, 0],
           [0, 0, 0],
           [0, 0, 0]])
    

    我们可以用标量设置值:

    In [32]: res[mask] = 255                                                        
    In [33]: res                                                                    
    Out[33]: 
    array([[[  0,   0,   0],
            [255, 255, 255],
            [255, 255, 255]],
    
           [[255, 255, 255],
            [  0,   0,   0],
            [  0,   0,   0]]])
    

    或数组:

    In [34]: res[mask] = [255,255,255]                                              
    In [35]: res                                                                    
    Out[35]: 
    array([[[  0,   0,   0],
            [255, 255, 255],
            [255, 255, 255]],
    
           [[255, 255, 255],
            [  0,   0,   0],
            [  0,   0,   0]]])
    

    有时在设置这样的掩码数组时,我们会遇到广播错误 - 目标数组和源数组不匹配。

    另一种方法是将 mask 视为 0/1 索引数组:

    In [37]: x = np.array([[0,0,0],[255,255,255]])                                  
    In [39]: x[mask.astype(int)]                                                    
    Out[39]: 
    array([[[  0,   0,   0],
            [255, 255, 255],
            [255, 255, 255]],
    
           [[255, 255, 255],
            [  0,   0,   0],
            [  0,   0,   0]]])
    

    如果您从列表开始,列表理解方法可能是最快的。虽然数组索引速度很快,但将列表转换为数组的开销很大。

    ====

    要使用np.vectorize 执行此操作,我使用signature,它比常规vectorize 慢:

    In [49]: np.vectorize(lambda y: np.array([255,255,255]) if y else np.array([0,0,
        ...: 0]), signature='()->(n)')(alist)                                       
    Out[49]: 
    array([[[  0,   0,   0],
            [255, 255, 255],
            [255, 255, 255]],
    
           [[255, 255, 255],
            [  0,   0,   0],
            [  0,   0,   0]]])
    

    【讨论】:

      【解决方案3】:

      你可以使用np.where:

      In [11]: np.where(a, np.array([255, 255, 255]), 0)
      Out[11]:
      array([[255, 255, 255],
             [  0,   0,   0],
             [255, 255, 255]]
      

      另一种方法是先创建一个完整数组或零数组,然后更新行:

      In [21] res = np.zeros((3, 3))
      
      In [22]: np.where(a == 0, res, 255)
      Out[22]:
      array([[255., 255., 255.],
             [  0.,   0.,   0.],
             [255., 255., 255.]])
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-05-05
        • 2016-02-14
        • 2021-05-14
        • 1970-01-01
        • 1970-01-01
        • 2020-10-10
        • 1970-01-01
        • 2020-05-30
        相关资源
        最近更新 更多