title: Passing list of lists as input to scipy.optimize.curve_fit
body: <p>I am trying to solve an example marketing mix model problem using python and the curve_fit function.</p>
  
  <p>I need to fit two sets of parameters, which i add to my function as a * arg list of lists. I can get the curve fit to work for one set of parameter (a single list) but not two.</p>
  
  <h1>Code</h1>
  
  <pre><code>#import packages
  from scipy.optimize import curve_fit
  import pandas as pd
  import numpy as np
  from statsmodels.tsa.filters.filtertools import recursive_filter as rec
  </code></pre>
  
  <h2>Dataset</h2>
  
  <pre><code>a = np.array(0).repeat(150)
  b = np.array(0).repeat(150)
  c = np.array(0).repeat(150)
  a[0:90] = np.random.uniform(5,10,(90,))
  b[50:150] = np.random.uniform(20,40,(100,))
  c[30:100] = np.random.uniform(5,25,(70,))
  df = pd.DataFrame({'a':a,'b':b,'c':c})
  </code></pre>
  
  <h1>Fitting one set of parameters</h1>
  
  <pre><code>def mmm(data,*param):
      dic = {}
      j = 0
      for i in data:
          dic[i] = rec(data[i],param[j])
          j += 1
      return(np.sum(pd.DataFrame(dic),1))
  </code></pre>
  
  <p>The function, applies the recursive filter to each field in the data argument with a different lambda parameter and returns the dataframe row sum.</p>
  
  <pre><code>kpi = mmm(df,*(0.5,0.5,0.1)) + np.random.uniform(-5,5)
  </code></pre>
  
  <p>When passing a *argument to the scipy curve fit function you have to define a function that outputs a function. As described here:<a href="https://stackoverflow.com/questions/18326524/pass-tuple-as-input-argument-for-scipy-optimize-curve-fit?noredirect=1&amp;lq=1">Pass tuple as input argument for scipy.optimize.curve_fit</a> </p>
  
  <h2>Fit the curve</h2>
  
  <pre><code>a = np.zeros(3)
  def make_func():
      def mmm(data,*param):
          dic = {}
          j = 0
          for i in data:
              dic[i] = rec(data[i],param[j])
              j += 1
          return(np.sum(pd.DataFrame(dic),1))
      return(mmm) 
  leastsq, covar = curve_fit(make_func(),df,kpi,a)
  
  print(leastsq)
  array([0.87560795, 0.87192766, 0.84864161])
  </code></pre>
  
  <h1>Fitting two sets of parameters</h1>
  
  <pre><code>def mmm(x,*arg):
      c = args[0]
      a = args[1]
      dic = {}
      j = 0
      for i in x:
          dic[i] = c[j] * rec(x[i], a[j])
          j += 1
      return(np.sum(pd.DataFrame(dic),1))   
  </code></pre>
  
  <p>The function, applies the recursive filter to each field in the data argument with a different lambda (a), multiplies it by a scalar (c) and takes the row sum of the dataframe.</p>
  
  <pre><code>args = [[4,5,3],[0.2,0.4,0.5]]
  kpi = mmm(df,*args) + np.random.uniform(-5,5)
  </code></pre>
  
  <h2>Fit the curve</h2>
  
  <pre><code>args = np.zeros(6)
  def make_func():
      def mmm(x,*args):
          c = args[0]
          a = args[1]
          dic = {}
          j = 0
          for i in x:
              dic[i] = c[j] * rec( x[i], a[j])
              j += 1
          return(np.sum(pd.DataFrame(dic),1))
      return(make_func)
  leastsq, covar = curve_fit(make_func,df, kpi, p0=args)
  </code></pre>
  
  <p>Using the same method as for one list of parameters spits out an error for two. The error is as follows:</p>
  
  <pre><code>TypeError: make_func() takes 0 positional arguments but 7 were given
  </code></pre>
  
  <p>Is there something else, i have to do in order to get this code working?</p>
  
  <p>Cheers,</p>