1

I am writing a function that needs to contain a subfunction in order to run the curve_fit function from the scipy.optimize module. The issue is that the number of variables that goes into the subfunction (let's call it fitFunc) depends on how many columns are in the dataframe input into the main function. Below is my code:

def function(mod_data):
    import numpy as np
    i = 0
    ps = len(mod_data.columns) - 7
    temp = '(xdat[0]**b)'

    while i != (ps-1):
        dummypy = '(xdat[' + str(i+1) + ']'
        temp = temp + '+' + dummypy + '**b)'
        i += 1

    xdat = mod_data.iloc[:,7:].values
    xdat = np.transpose(xdat)
    ydat = mod_data.iloc[:,1].values

    form = 'def fitFunc(xdat, a, b): return (a/ps) * (%s)' % temp
    exec(form)
    result = curve_fit(fitFunc, xdat, ydat, 
                       p0 = np.array([100000,.75]))
    return result

Above mod_data is the dataframe that contains the variables for the modeling process. form should be the following character string if xdat has two or three rows respectively:

# xdat has 2 rows
form = 'def fitFunc(xdat, a, b): return (a/ps) * ((xdat[0]**b)+(xdat[1]**b))'

# xdat has 3 rows
form = 'def fitFunc(xdat, a, b): return (a/ps) * ((xdat[0]**b)+(xdat[1]**b)+(xdat[2]**b))'

I realize that I could just define the function, but the issue is that I don't know how many variables will actually be in the dataframe before it's entered into the function, so I run through the final columns in order to find that number, then write have the code write the function for me depending on how many variables there will be.

I know from this previous question that exec doesn't work when there are subfunctions in the function: Why doesn't exec work in a function with a subfunction? . So my goal here is to find another way to define the fitFunc subfunction depending on how many variables xdat will have from the mod_data dataframe. Thanks in advance for any advice.

obewanjacobi
  • 458
  • 2
  • 12

1 Answers1

1

There's no need to create the function dynamically and use exec. Just iterate over xdat.

def fitFunc(xdat, a, b):
    return (a/ps) * sum(x**b for x in xdat)
Barmar
  • 741,623
  • 53
  • 500
  • 612