使用if语句优化作用于numpy数组的函数

时间:2017-12-11 00:22:08

标签: python arrays numpy

假设我有一个代码:

import numpy as np

def value_error(x):
    if x > 10:
        return 0.
    else:
        return np.sin(x)

如果调用numpy数组,这可能会给我一个ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

现在我可以这样做:

def alright(x):
    return np.sin(x) * (x <= 10.)

print alright(np.ones(100) * 100)
print value_error(np.ones(100) * 10)

我的功能(在这种情况下为np.sin)可能是一个昂贵的功能。然而,它被称为x的每个元素,甚至是我知道答案的元素,因为x > 10,没有昂贵的电话。我如何才能充分利用这两个世界?

3 个答案:

答案 0 :(得分:4)

许多ufunc采用where参数

In [98]: x=np.arange(10)*2
In [99]: mask = x<10
In [100]: y = np.zeros(10)
In [101]: np.sin(x,where=mask,out=y)
Out[101]: 
array([ 0.        ,  0.90929743, -0.7568025 , -0.2794155 ,  0.98935825,
        0.        ,  0.        ,  0.        ,  0.        ,  0.        ])

虽然这是一个很小的案例,timeit表明它没有比使用@ {divakar的答案mask更有优势:

In [104]: timeit np.sin(x,where=mask,out=y)
5.17 µs ± 12.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [105]: timeit y[mask] = np.sin(x[mask])
4.69 µs ± 9.54 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

(对于更大的xwhere参数与mask使用相比具有轻微的时间优势。)

答案 1 :(得分:2)

请注意,您的函数不会利用numpy的矢量化。有几种可能的选择。

选项1
这似乎是np.where -

的一个很好的用例
y = np.where(x > 10, 0, np.sin(x))

根据提供的掩码返回值。这是一个样本 -

x
array([  0.1,   0.2,   0.3,  11. ,   0.1,  11. ])

np.where(x > 10, 0, np.sin(x))
array([ 0.09983342,  0.19866933,  0.29552021,  0.        ,  0.09983342,  0.        ])

请注意,此方法仍会为每个元素调用“昂贵的函数”。

选项2
另一种可能性是使用掩码并有条件地设置值 -

y = np.sin(x)
y[x > 10] = 0

与上述类似,您可以将x乘以掩码并在结果上调用np.sin -

y = np.sin(x * (x < 10))

正如Divakar所提到的,你可以在这种情况下使用numexpr -

import numexpr as ne
y = ne.evaluate("sin(x * (x < 10))")

这应该比上面的更快。

答案 2 :(得分:2)

这是一个基于掩码的掩码,只对有效的@shared_task def get_report(name): sleep(30) @shared_task def set_task_status(id): instance = Scorecard.objects.get(task_id=id) task_status = AsyncResult(id) instance.status = task_status.status instance.save() 进行操作 -

np.sin

利用numexpr module加快out = np.zeros(x.shape) mask = x <= 10 out[mask] = np.sin(x[mask]) 次操作 -

transcendental