Условная кусочная функция - PullRequest
1 голос
/ 17 апреля 2019

Это может быть легче объяснить, предоставив мою попытку, затем мое намерение + комментарии.

import numpy as np
from numpy import sqrt, arcsin, arcsinh

# Returns roots of quadratic (or lack of)
def roots(a, b, c):
    b24ac = b*b - 4*a*c
    if a == 0 or b24ac < 0:
        return np.nan, np.nan
    else:
        l = (-b - sqrt(b24ac))/(2*a)
        r = (-b + sqrt(b24ac))/(2*a)
        if l > r:
            l, r = r, l
        return l, r

# Some numeric functions
def pw1(z, a, b, c):
    return -arcsin((2*a*z+b)/sqrt(b*b - 4*a*c))/sqrt(-a)

def pw2(z, a, b, c):
    return arcsinh((2*a*z+b)/sqrt(4*a*c - b*b))/sqrt(a)

# Function incorporating above definitions w/ conditions/domains
def func(z, a, b, c):
    b24ac = b*b - 4*a*c
    l, r = roots(*abc)
    conditions = [(b24ac > 0 and a < 0) and (l < z and z < r),
                  (b24ac < 0 and a > 0)]
    choices = [pw1(z, a, b, c), 
               pw2(z, a, b, c)] 
    return np.select(conditions, choices)

Это моя попытка создать функцию python, которая является условной кусочной функцией. Для математически любопытных это часть полного определения интеграла от $ [ax ^ 2 + bx + c] ^ {- 1/2} $. Необходимая специфика заключается в том, что мне нужна функция, которая зависит от домена и других параметров. Я изучил функции piecewise и select numpy. Piecewise, для своего списка условий, принимает только логику в домене (не параметры). Если я что-то упустил, похоже, это не сработает для меня. Select дал мне самый большой успех. Единственные проблемы, которые у меня были, это то, что он не оценивал условия домена по домену:

--->  conditions = [(b24ac > 0 and a < 0) and (l < z and z < r),
                  (b24ac < 0 and a > 0)]

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Наконец, он оценивает все варианты (которые являются результатами в отличие от функций , которые вы даете piecewise), затем выбирает один из них в списке условий для возврата (комментируя and (l < z. .. условия):

c:\program files\python36\lib\site-packages\ipykernel_launcher.py:6: 
RuntimeWarning: invalid value encountered in sqrt

Я начал эту неделю с нескольких elif заявлений. Это работало только для поплавков, а не массивов. Я использую NumPy, и мне нужна эта функция (или любая другая) для оценки по домену. Затем я узнал о piecewise и select и начал играть с ними, будучи от numpy.

Я бы очень хотел питонский способ сделать это. Тот, который оценивает по массивам NumPy и только для желаемого условия / домена. Таким образом, ведет себя как piecewise, но имеет универсальные условия, такие как select. Любая помощь и предложения с благодарностью! Спасибо.

1 Ответ

0 голосов
/ 17 апреля 2019

Идентификатор b24ac, безусловно, носит описательный характер, но большинство людей, вероятно, назвали бы это discriminant.

используйте свой собственный

Вы жалуетесь, что знаете, как рассчитать желаемый результат, но пупырчатые инструменты под рукой не кажутся подходящими. Поэтому напишите свою собственную функцию fn и используйте .apply(fn) или nditer . Обратите внимание, что вы можете расположить все необходимые аргументы в дополнительных столбцах, и пусть функция обрабатывает строку за раз.

Я не слышал о скорости, который будет обычным аргументом против такой пользовательской функции.

использовать np.piecewise

Я согласен с вами, что кусочно () , кажется, соответствует вашим потребностям. Аспект, который, казалось, отсутствовал, настраивал ваши функции с четырьмя параметрами прежде чем передать их кусочно. Для этой цели хорошо подойдет functools.partial () .

...