3

Given an array of x and y values, the following code will calculate a regression curve for these data points.

# calculate polynomial
z = np.polyfit(x, y, 5)
f = np.poly1d(z)

# calculate new x's and y's
x_new = np.linspace(x[0], x[-1], 50)
y_new = f(x_new)

plt.plot(x,y,'o', x_new, y_new)
plt.xlim([x[0]-1, x[-1] + 1 ])
plt.show()

How can I use the above to derive the actual equation for this curve?

ali_m
  • 71,714
  • 23
  • 223
  • 298
123
  • 8,733
  • 14
  • 57
  • 99

4 Answers4

8

If you want to show the equation, you can use sympy to output latex:

from sympy import S, symbols, printing
from matplotlib import pyplot as plt
import numpy as np

x=np.linspace(0,1,100)
y=np.sin(2 * np.pi * x)

p = np.polyfit(x, y, 5)
f = np.poly1d(p)

# calculate new x's and y's
x_new = np.linspace(x[0], x[-1], 50)
y_new = f(x_new)

x = symbols("x")
poly = sum(S("{:6.2f}".format(v))*x**i for i, v in enumerate(p[::-1]))
eq_latex = printing.latex(poly)

plt.plot(x_new, y_new, label="${}$".format(eq_latex))
plt.legend(fontsize="small")
plt.show()

the result:

enter image description here

topher217
  • 1,188
  • 12
  • 35
HYRY
  • 94,853
  • 25
  • 187
  • 187
3

Construct a simple example:

In [94]: x=np.linspace(0,1,100)
In [95]: y=2*x**3-3*x**2+x-1

In [96]: z=np.polyfit(x,y,3)
In [97]: z
Out[97]: array([ 2., -3.,  1., -1.])

The z coefficients correspond to the [2,-3,1,-1] I used to construct y.

In [98]: f=np.poly1d(z)
In [99]: f
Out[99]: poly1d([ 2., -3.,  1., -1.])

The str, or print, string for f is a representation of this polynomial equation. But it's the z coeff that defines the equation.

In [100]: print(f)
   3     2
2 x - 3 x + 1 x - 1
In [101]: str(f)
Out[101]: '   3     2\n2 x - 3 x + 1 x - 1'

What else do you mean by 'actual equation'?

polyval will evaluate f at a specific set of x. Thus to recreate y, use polyval(f,x):

In [107]: np.allclose(np.polyval(f,x),y)
Out[107]: True
hpaulj
  • 221,503
  • 14
  • 230
  • 353
0

If you only want to see the equation on your screen to get an impression about the equation, you only need to add the below line:

print(f)

Here comes more details:

polyfit returns a vector of coefficients of the polynomial fit. poly1d takes this vector and make a polynomial function out of it.

For example (from Numpy documentation for poly1d ):

p = np.poly1d([1, 2, 3])
>>> print(np.poly1d(p))
   2
1 x + 2 x + 3
  • It is important when providing an answer, that you include an explanation so others may learn from your response. Please edit your response to include a more complete explanation of how your recommended solution resolves this question. – itprorh66 Jul 21 '21 at 23:36
0

Or, build a string in a loop (this one expects coefficients for increasing order terms, so use np.flip(np.polyfit()), and pass the output to the following function.

def polyname(poly):
    name = f"$y = {round(poly[0],2)}$"
    for i in range(1, len(poly)):
        if i == 1:
            if poly[i] >= 0:
                name = name + f"$ + {round(poly[i],2)}x$"
            else:
                name = name + f"$ - {abs(round(poly[i],2))}x$"
        else:
            if poly[i] >= 0:
                name = name + f"$ + {round(poly[i],2)}x^{{{i}}}$"
            else:
                name = name + f"$ - {abs(round(poly[i],2))}x^{{{i}}}$"

    return name
bt3
  • 156
  • 1
  • 10