Reputation: 709
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)
Upvotes: 4
Views: 1856
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
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.
Upvotes: 2