条件分段函数

问题描述 投票:1回答:1

通过提供我到目前为止的尝试,然后我的意图+评论,这可能更容易解释。

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} $的积分的完整定义的一部分。必要的细节是我需要一个以域和其他参数为条件的函数。我已经研究了numpy的piecewiseselect函数。 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,并且正在使用此功能(或任何真正的)评估域名是我所追求的。然后我了解了piecewiseselect并开始玩这些,来自numpy。

我真的很喜欢这样做的pythonic方法。一个用于评估numpy数组,仅用于所需的条件/域。所以,表现得像piecewise,但有像select这样的多功能调节。非常感谢任何帮助和建议!谢谢。

python python-3.x numpy condition piecewise
1个回答
0
投票

b24ac标识符当然是描述性的,但大多数人可能会将其命名为discriminant

use your own

你抱怨你知道如何计算所需的结果,但手头的numpy工具似乎不太适合。所以编写自己的函数fn并使用.apply(fn)nditer。请注意,您可以安排所有需要的参数出现在额外的列中,并让函数一次处理一行。

我听说没有关于速度的问题,这是反对这种自定义函数的通常论据。

use np.piecewise

我同意你的观点,piecewise()似乎适合您的需求。似乎缺少的方面是在将它们传递给分段之前用四个参数定制你的函数。这种需求的良好匹配将是functools.partial()

© www.soinside.com 2019 - 2024. All rights reserved.