Ndarray
有一个成员函数extract
来提取满足某些条件的数组元素。但是,此功能比花式索引慢。我们为什么要使用这个功能?
from numpy import *
a=random.random((1000,2000))
b=a>0.2
%timeit extract(b,a)
%timeit a[b]
%timeit extract(a>0.2,a)
%timeit a[a>0.2]
这是我的输出:
In [138]: %timeit extract(b,a)
10 loops, best of 3: 29.6 ms per loop
In [139]: %timeit a[b]
100 loops, best of 3: 18.5 ms per loop
In [140]: %timeit extract(a>0.2,a)
10 loops, best of 3: 31.4 ms per loop
In [141]: %timeit a[a>0.2]
10 loops, best of 3: 19.7 ms per loop
答案 0 :(得分:1)
如果我们检查np.extract
,我们会发现以下内容:
take(a.ravel(), nonzero(ravel(b))[0])
这里有趣的是我们取b
这是一个布尔数组并将其转换为索引,以便正常的np.take
操作可以像宣传的那样工作。如果我们检查这需要多长时间,我们会发现nonzero
占总时间的大部分时间,并且花哨索引所需的时间少于nonzero
:
%timeit nonzero(ravel(b))[0]
100 loops, best of 3: 13.1 ms per loop
%timeit take(a.ravel(), nonzero(ravel(b))[0])
100 loops, best of 3: 18.7 ms per loop
%timeit a[b]
100 loops, best of 3: 12.9 ms per loop
docs解释说即使是花哨的索引也会使用某种类似nonzero
的操作来创建索引数组;但是,花哨的索引不涉及python抽象层。我相信python抽象层是这里的关键。到底究竟是什么,我不打算推测,但我希望当函数纯粹在C方面时会发生很多优化(就像所有花哨的索引一样)。