Sai Kiran
Sai Kiran

Reputation: 11

How to pass data frame series or array to exponential function while calculating curvefit

I am trying to fit using the scipy.optimize module.

My Exponential function:

a - (a - b) np.exp( -(c + Q / V) * t )

I need to find out a, b, c from the equation by optimizing.

V = 1200 # constant

my data frame looks like this:

time(t)   value    score(Q)
1.0       2.347    4500
2.0       2.345    4600
3.0       2.523    4655
4.0       2.723    4500
    ...
    ...
100.0    5.6787    7000
    ...

Values in the "value" field increases in a linear way.

My fit function for the above exponential:

def my_exp(Q, t, a, b, c): #just added Q here  
    V = 1280
    return a - (a - b) np.exp( -(c + Q / V) * t )

# Q = 5000 #mean value from column score
# getting values
c, cov = curve_fit(lambda t, a, b, c: my_exp(Q, t, a, b, c), df['time'], df['value'])

scenario 1: when "score" column is not given, provided constant has to be passed like(ex: Q = 5000) I tried with taking mean value from the score series and it's working.

scenario 2: when "score" column is given, send "score" series to the exponential function Q should be providing the score value at each time point

How can I send "score" series array values to the Q in exponential function to get an optimized value?

Is it the correct way of doing curve_fit for the above-mentioned data or do I need to follow any other curve fitting models?

Upvotes: 1

Views: 76

Answers (1)

mikuszefski
mikuszefski

Reputation: 4043

Hi as a dirty work around you could do just the following:

  • do not pass Q as argument.
  • make Q a global list
  • as t are basically integer call inside of my_epx the value of Q via Q[ int( round( t ) ) ]

Edit/AddOn

This should make it clear:

import numpy as np
from scipy.optimize import curve_fit

# setting static values
v = 2500
qlist = [ np.random.randint(4500, 4650 ) for i in range( 15 ) ]
tlist = np.arange( 1, 16 )
noiselist = np.random.normal( 0, 0.3, 15 )
a0 = 5
b0 = 2.2
c0 = -.78

# simple function checking for iterable first argument
def my_exp( t, a, b, c):
    if isinstance( t, ( list, tuple, np.ndarray ) ):
        out = np.fromiter( ( my_exp( tt, a, b, c) for tt in t ), np.float )
    else:
        localindex = int( round ( t ) ) - 1 ## -1 as t starts at 1 but index at 0
        localq = qlist[ localindex ]
        out = a - ( a - b ) * np.exp( -( c + localq / v ) * t )
    return out

# creating some test data with noise
testdata = my_exp( tlist, a0, b0, c0 )
testdatanoisy = testdata + noiselist

# fitting, does not even require start values
sol, _ = curve_fit( my_exp, tlist, testdatanoisy )
print sol
# works

which gives something like:

>> [ 4.89673111,  1.70423291, -0.72995739 ]

Upvotes: 0

Related Questions