I am trying to curve fit my defined function to a dataset. I defined my function using pandas and it prints the values. But when I try to optimize it using Curve_fit, it gives me an error that "list index out of range". I don't understand why?
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
ydata=np.array([1.2,1.21,1.2,1.19,1.21,1.22,1.8,2.47,2.49,2.49,2.5])
xdata = np.linspace(0,1,num=11).round(2)
def halfTrapz(x, m, a, tau1, tau2):
y = np.zeros(len(x))
dfy = pd.DataFrame(list(zip(x,y)),columns=['x','y'])
ta1=dfy.index[dfy['x']==tau1].tolist()
ta2=dfy.index[dfy['x']==tau2].tolist()
# ta1=list(np.array(ta1)+1)
# ta2=list(np.array(ta2)+1) #In order to consider ta2 in [:ta2]
dfy.iloc[:ta1[0],1] = a
b = a - m*dfy.iloc[ta1[0],0]
dfy.iloc[ta1[0]:ta2[0],1] = m * dfy.iloc[ta1[0]:ta2[0],0] + b
dfy.iloc[ta2[0]:,1] = m * dfy.iloc[ta2[0],0] + b
return dfy['y']
z=(halfTrapz(xdata, 5,1.2,0.5,0.7))
plt.plot(xdata,z,'g--')
plt.plot(xdata,ydata)
#First section (above) works fine for some given value and it can plot the function. However. second part when I try to use curve_fit this function. It gives me error.
from scipy.optimize import curve_fit
popt, pcov = curve_fit(halfTrapz, xdata, ydata)
print(popt)
print(pcov)
plt.plot(xdata, func(xdata, *popt), 'r-')
The message "list index out of range" means exactly what it says: you are trying to access a list element that doesn't exist. In this case it's caused because ta1
can be an empty list, and you are trying to access the 0th element here dfy.iloc[:ta1[0],1] = a
Now why would ta1
be empty? The offending statement is this one dfy['x']==tau1
. You are filtering based on a comparison here, but tau1
can be a float
, hence you are going to have headaches with float comparison. e.g 1.0==1.0000001
evaluates to False
.
I don't pretend to understand the math here, but if you really want to filter on a float field I suggest using something like np.isclose
.