简体   繁体   English

NumPy分段vs NumPy其中

[英]NumPy piecewise versus NumPy where

In what specific situations would np.piecewise be more convenient (less verbose) or computationally speeder than np.where , in evaluating a piecewise function on an array? 在什么特定情况下, np.piecewise在计算数组上的分段函数时会比np.where更方便(较不冗长)或计算速度更快? I'm having trouble seeing such a case, and I seem to run across piecewise functions being evaluated more often with where . 我在遇到这种情况时遇到麻烦,而且似乎遇到了更多使用where进行评估的分段函数。

np.piecewise seems to be more verbose regardless of number of pieces: 无论件数多少, np.piecewise似乎都比较冗长:

import numpy as np
b = np.arange(10, 20, dtype=np.float)

# 2 pieces - piecewise is more verbose
a = np.piecewise(b, [b<14, b>=14], [lambda x: x**2, lambda x: x/2])
c = np.where(b>=14, b/2, b ** 2)
print(np.array_equal(a, c))
True

# 3 pieces - piecewise still more verbose (won't it always be?)
d = np.piecewise(b, [b<11, np.logical_and(b>=11, b<14), b>=14], 
                 [1, lambda x: x**2, lambda x: x/2])
e = np.where(b>=14, b/2, np.where(b>=11, b**2, 1))
print(np.array_equal(d, e))
True

It is also significantly slower: 它也明显慢一些:

from timeit import timer
# variables above redefined as callables with no args
print('times:\n a: %d, c: %d, d: %d, e: %d' 
      % (timeit(a), timeit(c), timeit(d), timeit(e)))
times:
 a: 17, c: 4, d: 21, e: 7

piecewise is faster, if the calculation is slow, because only the values, that are needed are calculated. 如果计算速度较慢,则piecewise速度会更快,因为只会计算所需的值。

Shorter version: 较短的版本:

d = np.piecewise(b, [b<11, (b>=11)&(b<14)], [1, lambda x: x**2, lambda x: x/2])

In case it helps you decide, here's what piecewise is doing: 在情况下,它可以帮助你确定,这里就是piecewise做:

In [2]: b = np.arange(10,20,dtype=float)

define the 2 input lists; 定义2个输入列表; note that condition(s) are evaluated now. 请注意,现在评估条件。

In [12]: condlist = [b<14, b>=14]
In [13]: condlist
Out[13]: 
[array([ True,  True,  True,  True, False, False, False, False, False, False], dtype=bool),
 array([False, False, False, False,  True,  True,  True,  True,  True,  True], dtype=bool)]
In [14]: fnlist = [lambda x: x**2, lambda x: x/2]

piecewise just iterates on the 2 lists, and assigns values to the target array: piecewise迭代2个列表,并将值分配给目标数组:

In [15]: a = np.zeros_like(b)
In [16]: for k in range(len(condlist)):
    ...:     idx = condlist[k]
    ...:     a[idx] = fnlist[k](b[idx])
    ...:     
In [17]: a
Out[17]: 
array([ 100. ,  121. ,  144. ,  169. ,    7. ,    7.5,    8. ,    8.5,
          9. ,    9.5])

In [18]: np.piecewise(b, condlist, fnlist)
Out[18]: 
array([ 100. ,  121. ,  144. ,  169. ,    7. ,    7.5,    8. ,    8.5,
          9. ,    9.5])

This pair of where is similar, except the the fnlist calls are applied to the whole of b rather than a subset. 除了fnlist调用应用于整个b而不是子集之外,这对where相似。 In simple calculations like this it probably doesn't make much difference. 在像这样的简单计算中,它可能并没有太大区别。

In [21]: a = np.where(condlist[0], fnlist[0](b),0)
In [22]: a = np.where(condlist[1], fnlist[1](b),a)
In [23]: a
Out[23]: 
array([ 100. ,  121. ,  144. ,  169. ,    7. ,    7.5,    8. ,    8.5,
          9. ,    9.5])

In some cases it is wrong to evaluate a function over the whole range of b values - for example if it involves division by 0. The selective evaluation of piecewise would be better. 在某些情况下,在b值的整个范围内评估函数是错误的-例如,如果涉及除以0的情况。分段的选择性评估会更好。

Verbosity shouldn't be a significant measure. 详细程度不是一个重要的衡量指标。 We've already spent more time typing that question and answers. 我们已经花了更多时间输入问题和答案。 In working code, wordy code can be hidden in functions. 在工作代码中,冗长的代码可以隐藏在函数中。 Readability is more important in the long run. 从长远来看,可读性更为重要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM