Ограничение подвыражения в numexpr

Как эффективно выразить следующее с помощью numexpr?

z = min(x-y, 1.0) / (x+y)

Здесь x и y — несколько больших массивов NumPy одинаковой формы.

Другими словами, я пытаюсь ограничить x-y до 1.0 перед делением на x+y.

Я хотел бы сделать это, используя одно выражение numexpr (x и y огромны, и я не хочу перебирать их более одного раза).


person NPE    schedule 05.06.2012    source источник
comment
Просто чтобы быть ясным (поскольку min (x-y, 1) не является допустимым числом), вы хотите ограничить x-y до верхней границы 1 перед делением на (x + y)?   -  person DSM    schedule 05.06.2012
comment
@DSM: Да, это именно то, что я пытаюсь сделать. Я отредактировал вопрос.   -  person NPE    schedule 06.06.2012


Ответы (1)


Может быть, что-то вроде этого сработает?

In [11]: import numpy as np
In [12]: import numexpr as ne    
In [13]:     
In [13]: x = np.linspace(0.02, 5.0, 1e7)
In [14]: y = np.sin(x)
In [15]:     
In [15]: timeit z0 = ((x-y) - ((x-y) > 1) * (x-y - 1))/(x+y)
1 loops, best of 3: 1.02 s per loop
In [16]: timeit z1 = ne.evaluate("((x-y) - ((x-y) > 1.) * ((x-y) - 1.))/(x+y)")
10 loops, best of 3: 120 ms per loop    
In [17]: timeit z2 = ne.evaluate("((x-y)/(x+y))")
10 loops, best of 3: 103 ms per loop

Есть штраф за ограничение выше дивизиона, но это не так уж плохо. К сожалению, когда я попробовал это для некоторых больших массивов, это дало сбой. :-/

Обновление: это намного красивее и немного быстрее:

In [40]: timeit w0 = ne.evaluate("where(x-y>1,1,x-y)/(x+y)")
10 loops, best of 3: 114 ms per loop
person DSM    schedule 05.06.2012