Alessandro Peca
Alessandro Peca

Reputation: 923

set limits to numpy polyfit

I have two arrays with some data. In particular, the y array contains percentages that can not exceed y = 100 value. The y values satisfy the condition y <100 but if I make a fit, the result is that the curve exceeds y = 100, as shown in the figure below.

Is there any way to make a curve fit that does not exceed y = 100?

import numpy as np
import matplotlib.pyplot as plt
import numpy.polynomial.polynomial as poly

x = [0.25,0.75,1.25,1.75,2.15,2.75,3.15,3.75,4.15,4.75,5.15,5.75]
y = [ 100.,100.,90.,69.23076923,47.36842105,39.13043478,   
     35.71428571,26.31578947,22.22222222,18.86792453,
     11.76470588,9.43396226]

coefs = poly.polyfit(x, y, 3)
ffit = poly.polyval(x, coefs)
plt.plot(x, ffit)
plt.show()

enter image description here

Upvotes: 0

Views: 5891

Answers (1)

Thomas K&#252;hn
Thomas K&#252;hn

Reputation: 9820

You can pass the polyfit function a list of degrees that you want to fit, which means that you can leave out certain degrees (for example the constant value). With a bit of manipulation you can get what you want.

Assuming that you want your fit function to reach 100 at your minimum x value (0.25), you can subtract that 100 from all y-values, subtract 0.25 from all x values and then fit a polynomial such that only the coefficients for the first, second and third degree terms are fit parameters, but not the zeroth (or constant) term. Then, after the fitting you can set that constant term to 100 and compute the new, fitted values. I adjusted your example code to illustrate what I mean:

import numpy as np
import matplotlib.pyplot as plt
import numpy.polynomial.polynomial as poly

fig, ax = plt.subplots()

x = np.array([0.25,0.75,1.25,1.75,2.15,2.75,3.15,3.75,4.15,4.75,5.15,5.75])
y = np.array([ 100.,100.,90.,69.23076923,47.36842105,39.13043478,   
     35.71428571,26.31578947,22.22222222,18.86792453,
     11.76470588,9.43396226])

x_new = np.linspace(x[0],x[-1], 100)

##the original way to fit
coefs = poly.polyfit(x, y, 3)
ffit = poly.polyval(x_new, coefs)

##the adjusted way to fit
coefs2 = poly.polyfit(x-0.25, y-100, [1,2,3])
coefs2[0] = 100
ffit2 = poly.polyval(x_new-0.25,coefs2)

ax.plot(x_new, ffit, label = 'without constraints')
ax.plot(x_new, ffit2, label = 'with constraints')
ax.plot(x, y, 'ro', label = 'data')
ax.legend()
plt.show()

The result looks like this:

result of the above code

Hope this helps.

Upvotes: 2

Related Questions