'The graph and the values of the data fitted formula for my data are wrong and I don't know how to fix them

Problem in data fitting
Hi everyone, I'm quite new in Python and this is the first time I write on Stack Overflow. I've got a problem in fitting the data. With this code I would like to demonstrate a correlation between speed and heart rate in rowing. My code doesn't work properly in fact if i put the results in exponentialdata = exponential(x_data, ..., ..., ...) the graph it has moved upwards by 150 units. Also if I put the data that I estimated manually knowing a little of exponential proprieties the graph didn't fit so well the data (I send you herewith a picture). I think that the first two value calculated are correct or very close but the third should be around 5.2. Maybe someone has an idea for a better equation for this data.

Graph with values calculated by the code

Graph with tird value 5.2

This is the set of data that I used:

Pace (seconds);Stroke Rate;Heart Rate;Speed (m/s)
97;26;157;5.15
94.9;28;165;5.27
95.8;26;170;5.22
92.5;30;170;5.41
94;28;173;5.32
90.6;32;173;5.52
94.6;27;176;5.29
91.7;30;177;5.45
92;29;178;5.43
90;32;180;5.56
89.8;31;182;5.57
87.9;32;184;5.69

Is there anyone of you that can help me with these problems? I don't know how to do it, I've been stuck here for days. Thanks in advance and I hope I was clear enough in explaining my problems

This is my code:

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

## PACE-BPM ##
# Import CSV Data
with open("new 1 minuto 26-28-30-32.csv","r") as i:
    rawdata = list(csv.reader(i,delimiter = ";"))
exampledata = np.array(rawdata[1:], dtype=np.float)
x_data = exampledata[:,2]
y_data = exampledata[:,3] 

# Plot the Data
plt.figure(2,dpi=120)
plt.plot(x_data,y_data, 'o')
plt.title("Example Data")
plt.xlabel(rawdata[0][2])
plt.ylabel(rawdata[0][3])

#Define Function
def exponential(x, a, b, c):
  return a * np.exp(x-b) + c

#Evaluate and Plot Function
exponentialdata = exponential(x_data, 155, 188, 5.2)
plt.plot(x_data, exponentialdata, 'ro--', label="Model")
plt.legend()

#Curve fit data to model
popt, pcov = curve_fit(exponential, x_data, y_data,  bounds=(155,188))
perr = np.sqrt(np.diag(pcov))

fit_a = popt[0]
fit_b = popt[1]
fit_c = popt[2]

print(fit_a)
print(fit_b)
print(fit_c)

##########

# Show the plot
plt.show()


Solution 1:[1]

Basically your model is not well chosen. As a * exp(x -b) = a * exp(-b ) * exp(x) which is equivalent to a' exp(x). You need at least a a * exp( b * x ) + c.

With this I get a decent fit.

This is how mine is working:

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

exampledata = np.array([ 
    97, 26, 157, 5.15,
    94.9, 28, 165, 5.27,
    95.8, 26, 170, 5.22,
    92.5, 30, 170, 5.41,
    94, 28, 173, 5.32,
    90.6, 32, 173, 5.52,
    94.6, 27, 176, 5.29,
    91.7, 30, 177, 5.45,
    92, 29, 178, 5.43,
    90, 32, 180, 5.56,
    89.8, 31, 182, 5.57,
    87.9, 32, 184, 5.69
]).reshape( -1, 4)
print( exampledata )

#Define Function
def exponential(x, a, b, c):
  return a * np.exp( x * b ) + c


x_data = exampledata[:,2]
y_data = exampledata[:,3] 

# Plot the Data
fig = plt.figure( )
ax = fig.add_subplot( 1, 1, 1 )
ax.plot(x_data,y_data, 'o')
ax.set_title("Example Data")


#Evaluate and Plot Function
exponentialdata = exponential(x_data, 1.6e-6, 0.05,5.0)
plt.plot(x_data, exponentialdata, label="guess")

#Curve fit data to model
popt, pcov = curve_fit(exponential, x_data, y_data,  p0=(1e-6, 0.01,4.2),maxfev=1500)
ax.plot( x_data, exponential( x_data, *popt ), 'ro--',  label="Model")
perr = np.sqrt(np.diag(pcov))

plt.legend()

fit_a = popt[0]
fit_b = popt[1]
fit_c = popt[2]

print(fit_a)
print(fit_b)
print(fit_c)

##########

# Show the plot
plt.show()

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1