Python Forum
Using scipy.optimize: curve_fit - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: Data Science (https://python-forum.io/forum-44.html)
+--- Thread: Using scipy.optimize: curve_fit (/thread-38274.html)



Using scipy.optimize: curve_fit - ju21878436312 - Sep-24-2022

Hey there,

I would like to model exponential data by a curve_fit with scipy. The fit fits well for small x-values, but less so for bigger x-values. Is there anything I can do to improve the overall fit? Ideally, the measured data and fit should meet at the horizontal line of y = 0.01, since the slope in this area is important.

I have tried "trimming" the measured data, i.e. taking out small or large x-values, but did not really find a good solution. Are there any hinds or recommendations, what I could do to find a better solution? I have checked the documentation, but did not find anything useful for this specific case. I have also tried to combine my function with a scypy.optimize.minimize, but this did not work out either.

import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
from scipy.optimize import curve_fit 

# Create x and y values in dataframe
x_022_i = [2.0, 8.0, 14.0, 20.0, 26.0, 32.0, 38.0, 44.0, 50.0, 56.0, 62.0, 68.0, 74.0, 80.0, 92.0, 98.0, 104.0]
y_022_i = [1.043, 1.053, 1.343, 0.746, 0.544, 0.453, 0.248, 0.147, 0.056, 0.046, 0.041, 0.024, 0.011, 0.004, 0.002, 0.001, 0.001]

d = {'x_022_i': x_022_i, 'y_022_i': y_022_i}
df = pd.DataFrame(data=d)

# Define functions
def fun_datafit(xdata, ydata):
    popt, pcov = curve_fit(func,xdata,ydata)
    perr = np.sqrt(np.diag(pcov))
    return popt, pcov, perr

def func(x, b): 
    return np.exp(-b*x)

# Determine optimal parameter
popt_022_i, pcov_022_i, perr_022_i = fun_datafit(df["x_022_i"], df["y_022_i"])
b_opt = popt_022_i[0] 
print(popt_022_i[0])

# y-values fitted
y_022_i_fit = func(df["x_022_i"], b_opt)

# Plot
print(y_022_i_fit.iloc[12:13])
plt.plot(x_022_i,y_022_i,label="exp",marker='o', linestyle= 'None') # original data
plt.plot(x_022_i,y_022_i_fit, label="fit") # fit
plt.hlines(0.01,0,100, color='k') # 1% concentration
plt.xlabel("Time")
plt.ylabel("Normalized concentration")
plt.yscale("log")
plt.legend()
plt.show()