Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fit of two different functions with boarder as fit parameter

I have a question about a simple fit function in Python. I am trying to fit two different functions on a data set and the border between the two regimes should be also a fit parameter. Very naively I was trying something like this:

def FitFunc(x, a, b, c, d, e, border):
    if x < border:
        return a * x + b
    if x > border:
        return c * x**2 + d * x + e

But I got a ValueError:

The truth value of a Series is ambiguous. Use a.empty(), a.bool(), a.item(), a.any() or a.all()

I understand that you can not compare my x array to an integer value (which is not even assigned to a fixed value, this should be done by the curve_fit procedure).

I was not able to find a solution for this supposedly simple problem. Can someone help me out of this?

Thanks in advance!

EDIT: I constructed an example: Constructed example For the data with x<5 this is perfectly described by a linear function (y=x-3), For x>5 this is perfectly described by a square function (y=x**2/5-3*x/5). Assume you don't know that x is the perfect 'border', is there a way to let curve_fit find out?

like image 914
Hestu Avatar asked Nov 30 '25 14:11

Hestu


1 Answers

The error message is saying that comparing the values of an array (x) with a scalar value (border) is ambiguous. Do you mean if any values of x are less than border or if all values of x are less than border?

I suspect that what you really want is numpy's where function, which is sort of like looping over x and deciding which expression to use point-by-point, only much faster:

def FitFunc(x, a, b, c, d, e, border):
    out = a * x + b
    out[np.where(x > border)] = c * x**2 + d * x + e
    return out

I think that is what you want, and it should work to select the proper functional form based on border.

However, I would caution that it may not do what you want. That is, it looks like you intend border to be a fitting variable.

Fitting variables in scipy optimize routines (and most "curve fitting" contexts) need to be continuous floating point variables. Your border variable would be used as a discrete, integer value for the index of x to change functional form. The fitting algorithm will first choose a value (let's say 5.0), then make a very small change in that value (to, say, 5.0000002). That will not change where the breakpoint between your two functional forms is, and the fit will decide that border does not change the fit. I wish I knew a way around this.

like image 172
M Newville Avatar answered Dec 02 '25 05:12

M Newville



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!