numpy中的迭代器协议

时间:2019-03-24 17:53:07

标签: python numpy iterator

是否可以使用迭代器代替numpy中的numpy.ndarray

例如,假设我有一个2D数组,我想知道是否存在仅包含偶数的行:

import numpy as np

x = np.array([[1, 2], [2, 4], [3, 6]])
np.any(np.all(x % 2 == 0, axis=1))

有没有一种方法可以在不实例化内存中的中间对象的情况下进行此类操作? (或者也许已经是这样,我只是不知道)在此示例中,这意味着在[False True False]上使用迭代器而不是数组。换句话说,我们可以做等同于以下事情的事情吗?

has_an_even_row = False 
for row in x:
    if np.all(row % 2 == 0):
        has_an_even_row = True
        break

我的问题不仅涉及allany,而且涉及numpy中的所有函数/方法。如果不可能的话,我想知道是否有实际的原因在numpy中不使用它。 (也许每个人都认为这没用,这是一个很好的理由)

2 个答案:

答案 0 :(得分:1)

临时数组的数量可能比您想象的要多:

In [224]: x = np.array([[1, 2], [2, 4], [3, 6]])                                
In [225]: x % 2                                                                 
Out[225]: 
array([[1, 0],
       [0, 0],
       [1, 0]])
In [226]: _ == 0                                                                
Out[226]: 
array([[False,  True],
       [ True,  True],
       [False,  True]])
In [227]: np.all(_, axis=1)                                                     
Out[227]: array([False,  True, False])
In [228]: np.any(_)                                                             
Out[228]: True

在这种情况下,逐行工作将节省计算最后一行的值。

最后一个any步骤可能会短路,遇到True时就会停止-这是实现细节。

一个彻底的迭代,没有多余的计算方法将是这样的:

In [231]: val = False 
     ...: for row in x: 
     ...:     for col in row: 
     ...:         if col%2!=0: 
     ...:             break 
     ...:         val=(row,col) 
     ...:         break 

In [232]: val                                                                   
Out[232]: (array([2, 4]), 2)

如果我使用C或类似lisp的语言编写代码,那么测试,内存管理和计算都在同一代码级别进行,那么这种方法就很有意义。但这不是模块化或可重用的。

numpy的基本思想是提供一组全面的已编译构建基块。这些块并非对于所有任务都是最佳的,但总体而言,它们既快速又易于使用。

通常建议使用给定的构建块进行快速开发。一旦开始运作,就可以担心提高关键时间步骤的速度了。

答案 1 :(得分:1)

numpy库没有为您提供许多使用某些常规Python协议的工具,因为它专注于狭窄域(数字计算)中的性能。 numpy的全部目的是在不损失 all 的情况下更快地执行纯Python中缓慢的数字运算(接近硬件的最高速度,例如使用诸如C之类的底层语言编写的代码)。 em>具有Python的优势(例如垃圾收集和易于阅读的语法)。

专注于狭窄域的弊端是您失去了更通用代码的某些好处。因此,您的for循环代码比numpy的工作量少,因为它可以短路,一旦知道结果就可以中断迭代。如果它已经找到需要的结果,则不必为每一行都做模。

但是我怀疑如果您对其进行测试,您的numpy代码可能仍然会在很多时候更快(对真实数据进行测试,而不是像您的示例中那样琐碎的东西)!尽管它可以预先计算出一大堆中间结果,但低级操作比纯Python中的等效操作要快得多,因此不必遍历整个数组即可。