I want to fit a sum of a polynomial and a sine to a data set.
I do not manage to pass a set of initial values for the coefficients (initial guess) into the function. I know that the asterisk (*
) packs the variable.
I define the function
import pandas as pd
import numpy as np
from numpy.polynomial import Polynomial as P
def func(x,*A):
A=A[0] # to get the values only
polynom=P(A[0:-3]) # all but the last three coefficients go into the polynomial
sine=A[-3]*np.sin(A[-2]*(x-A[-1])) # the last three coefficients are for the sine
y=polynom(x) sine # sum up both
return y
Let's take some test values:
P0=(1,2,3,4,5,6,7,8,9,10,11)
The call of curve_fit fails:
coefs_scipy,pcov = sio.curve_fit(func,df.length,df.s,p0=P0)
where df
is a pandas dataframe, the columns length
and s
containing the x
and y
values respectively.
The last error is
\AppData\Local\Temp/ipykernel_16648/911748954.py in func(x, *A)
29 def func(x,*A):
30 A=A[0] # to get the values only
---> 31 polynom=P(A[0:-3]) # all but the last three coefficients go into the polynomial
32 sine=A[-3]*np.sin(A[-2]*(x-A[-1])) # the last three coefficients are for the sine
33 y=polynom(x) sine # sum up both
IndexError: invalid index to scalar variable.
indicating that it is not possible to extract [0:-3]
from a scalar. Though A
is not a scalar I assume
Astonishingly, when I just call the function with func(1,P0)
it works.
What is wrong?
CodePudding user response:
The curve_fit
function internally calls the target function like
func(x, *P0)
That means all the values in the P0 tuple are expanded into positional arguments to the function.
The function declaration
def func(x, *A):
...
collects all these positional arguments into A. So A is a tuple containing all the values and not a tuple of tuples.
To solve your problem, you should remove the
A=A[0]
line and change the direct call to the function to
func(1, *P0)