3

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?

Hestu
  • 33
  • 5

1 Answers1

2

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.

M Newville
  • 7,486
  • 2
  • 16
  • 29
  • I meant border like the point where one regime ends and the other begins. I am sorry if this led to confusion. I edited it in the original question. – Hestu Apr 25 '18 at 07:55
  • OK, I altered the answer to match the edited question. – M Newville Apr 25 '18 at 11:21