numpy.ma.polyfit(x, y, deg, rcond=None, full=False, w=None, cov=False)
[source]
Least squares polynomial fit.
Fit a polynomial p(x) = p[0] * x**deg + ... + p[deg]
of degree deg
to points (x, y)
. Returns a vector of coefficients p
that minimises the squared error in the order deg
, deg-1
, … 0
.
The Polynomial.fit
class method is recommended for new code as it is more stable numerically. See the documentation of the method for more information.
Parameters: |
|
---|---|
Returns: |
|
Warns: |
|
See also
polyval
linalg.lstsq
scipy.interpolate.UnivariateSpline
Any masked values in x is propagated in y, and vice-versa.
The solution minimizes the squared error
in the equations:
x[0]**n * p[0] + ... + x[0] * p[n-1] + p[n] = y[0] x[1]**n * p[0] + ... + x[1] * p[n-1] + p[n] = y[1] ... x[k]**n * p[0] + ... + x[k] * p[n-1] + p[n] = y[k]
The coefficient matrix of the coefficients p
is a Vandermonde matrix.
polyfit
issues a RankWarning
when the least-squares fit is badly conditioned. This implies that the best fit is not well-defined due to numerical error. The results may be improved by lowering the polynomial degree or by replacing x
by x
- x
.mean(). The rcond
parameter can also be set to a value smaller than its default, but the resulting fit may be spurious: including contributions from the small singular values can add numerical noise to the result.
Note that fitting polynomial coefficients is inherently badly conditioned when the degree of the polynomial is large or the interval of sample points is badly centered. The quality of the fit should always be checked in these cases. When polynomial fits are not satisfactory, splines may be a good alternative.
[1] | Wikipedia, “Curve fitting”, https://en.wikipedia.org/wiki/Curve_fitting |
[2] | Wikipedia, “Polynomial interpolation”, https://en.wikipedia.org/wiki/Polynomial_interpolation |
>>> import warnings >>> x = np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0]) >>> y = np.array([0.0, 0.8, 0.9, 0.1, -0.8, -1.0]) >>> z = np.polyfit(x, y, 3) >>> z array([ 0.08703704, -0.81349206, 1.69312169, -0.03968254]) # may vary
It is convenient to use poly1d
objects for dealing with polynomials:
>>> p = np.poly1d(z) >>> p(0.5) 0.6143849206349179 # may vary >>> p(3.5) -0.34732142857143039 # may vary >>> p(10) 22.579365079365115 # may vary
High-order polynomials may oscillate wildly:
>>> with warnings.catch_warnings(): ... warnings.simplefilter('ignore', np.RankWarning) ... p30 = np.poly1d(np.polyfit(x, y, 30)) ... >>> p30(4) -0.80000000000000204 # may vary >>> p30(5) -0.99999999999999445 # may vary >>> p30(4.5) -0.10547061179440398 # may vary
Illustration:
>>> import matplotlib.pyplot as plt >>> xp = np.linspace(-2, 6, 100) >>> _ = plt.plot(x, y, '.', xp, p(xp), '-', xp, p30(xp), '--') >>> plt.ylim(-2,2) (-2, 2) >>> plt.show()
© 2005–2019 NumPy Developers
Licensed under the 3-clause BSD License.
https://docs.scipy.org/doc/numpy-1.17.0/reference/generated/numpy.ma.polyfit.html