class_docstr: Todo:
  check treatment of const, make it optional ?
      add hasconst (0 or 1), needed when selecting nfact+hasconst
  options are arguments in calc_factors, should be more public instead
  cross-validation is slow for large number of observations
docstr: estimate the model and selection criteria for up to maxfact factors
  
  The selection criteria that are calculated are AIC, BIC, and R2_adj. and
  additionally cross-validation prediction error sum of squares if `skip_crossval`
  is false. Cross-validation is not used by default because it can be
  time consuming to calculate.
  
  By default the cross-validation method is Leave-one-out on the full dataset.
  A different cross-validation sample can be specified as an argument to
  cv_iter.
  
  Results are attached in `results_find_nfact`
code: def fit_find_nfact(
      self, maxfact=None, skip_crossval=True, cv_iter=None
  ):
      """estimate the model and selection criteria for up to maxfact factors
  
      The selection criteria that are calculated are AIC, BIC, and R2_adj. and
      additionally cross-validation prediction error sum of squares if `skip_crossval`
      is false. Cross-validation is not used by default because it can be
      time consuming to calculate.
  
      By default the cross-validation method is Leave-one-out on the full dataset.
      A different cross-validation sample can be specified as an argument to
      cv_iter.
  
      Results are attached in `results_find_nfact`
  
  
  
      """
      # print 'OLS on Factors'
      if not hasattr(self, "factors"):
          self.calc_factors()
  
      hasconst = self.hasconst
      if maxfact is None:
          maxfact = self.factors.shape[1] - hasconst
  
      if (maxfact + hasconst) < 1:
          raise ValueError(
              "nothing to do, number of factors (incl. constant) should "
              + "be at least 1"
          )
  
      # temporary safety
      maxfact = min(maxfact, 10)
  
      y0 = self.endog
      results = []
      # xred, fact, eva, eve  = pca(x0, keepdim=0, normalize=1)
      for k in range(
          1, maxfact + hasconst
      ):  # k includes now the constnat
          # xred, fact, eva, eve  = pca(x0, keepdim=k, normalize=1)
          # this is faster and same result
          fact = self.factors[:, :k]
          res = sm.OLS(y0, fact).fit()
          ##    print 'k =', k
          ##    print res.params
          ##    print 'aic:  ', res.aic
          ##    print 'bic:  ', res.bic
          ##    print 'llf:  ', res.llf
          ##    print 'R2    ', res.rsquared
          ##    print 'R2 adj', res.rsquared_adj
  
          if not skip_crossval:
              if cv_iter is None:
                  cv_iter = LeaveOneOut(len(y0))
              prederr2 = 0.0
              for inidx, outidx in cv_iter:
                  res_l1o = sm.OLS(y0[inidx], fact[inidx, :]).fit()
                  # print data.endog[outidx], res.model.predict(data.exog[outidx,:]),
                  prederr2 += (
                      y0[outidx]
                      - res_l1o.model.predict(
                          res_l1o.params, fact[outidx, :]
                      )
                  ) ** 2.0
          else:
              prederr2 = np.nan
  
          results.append(
              [k, res.aic, res.bic, res.rsquared_adj, prederr2]
          )
  
      self.results_find_nfact = results = np.array(results)
      self.best_nfact = np.r_[
          (
              np.argmin(results[:, 1:3], 0),
              np.argmax(results[:, 3], 0),
              np.argmin(results[:, -1], 0),
          )
      ]
  
file_path: statsmodels/statsmodels/sandbox/datarich/factormodels.py
imports: import numpy
  import statsmodels.api
  from statsmodels.sandbox.tools import pca
  from statsmodels.sandbox.tools.cross_val import LeaveOneOut
label_desc: Use image node_id 4 for calling the FactorModelUnivariate obj's underlying member method code with example usage: obj.fit_find_nfact(maxfact, skip_crossval, cv_iter) without return types