Silviu
Silviu

Reputation: 709

Fitting a curve with a pivot point Python

I have the plot below and I want to fit it with 2 lines. Using python I manage to fit the upper part:

def func(x,a,b):
    x=np.array(x)
    return a*(x**b)
popt,pcov=curve_fit(func,up_x,up_y)

And I want to fit the lower part with another line, but I want the line to pass through the point where the red one stars, so I can have a continuous function. So my question is how can I use curve_fit by giving a point the function has to pass through, but leaving the slope of the line to be calculated by python? (Or any other python package able to do it)

enter image description here

Upvotes: 4

Views: 1856

Answers (2)

Kevin Zhu
Kevin Zhu

Reputation: 2836

You can take a look at piecewise and pwlf. Below is an example using piecewise which can automatically fit multiple segments.

from piecewise.regressor import piecewise
import numpy as np

x = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ,11, 12, 13, 14, 15,16,17,18], dtype=float)
y = np.array([5, 7, 9, 11, 13, 15, 28.92, 42.81, 56.7, 70.59, 84.47, 98.36, 112.25, 126.14, 140.03,120,112,110])

model = piecewise(x, y)

Evaluate'model' to get the following output:

FittedModel with segments:
* FittedSegment(start_t=1.0, end_t=7.0, coeffs=(2.9999999999999996, 2.0000000000000004))
* FittedSegment(start_t=7.0, end_t=16.0, coeffs=(-68.2972222222222, 13.888333333333332))
* FittedSegment(start_t=16.0, end_t=18.0, coeffs=(198.99999999999997, -5.000000000000001))

Upvotes: -1

Christian K.
Christian K.

Reputation: 2823

A possible stepwise parametrisation of your model in log-space is something like:

(x>q)*((x-q)*a)+(x<q)*((x-q)*c)+b

Where q is the position of the kink, a, and c are the slopes of both parts and b is a global y-offset. Since the model has a discontinuity a gradient based minimizer might not be the best choice to find a best fit. Nevertheless I tried both scipy.optimize.leastsq and scipy.odr and got good results.

fit to noisy data

Upvotes: 2

Related Questions