code: def linear_rainbow(
      res, frac=0.5, order_by=None, use_distance=False, center=None
  ):
      """
      Rainbow test for linearity
  
      The null hypothesis is the fit of the model using full sample is the same
      as using a central subset. The alternative is that the fits are difference.
      The rainbow test has power against many different forms of nonlinearity.
  
      Parameters
      ----------
      res : RegressionResults
          A results instance from a linear regression.
      frac : float, default 0.5
          The fraction of the data to include in the center model.
      order_by : {ndarray, str, List[str]}, default None
          If an ndarray, the values in the array are used to sort the
          observations. If a string or a list of strings, these are interpreted
          as column name(s) which are then used to lexicographically sort the
          data.
      use_distance : bool, default False
          Flag indicating whether data should be ordered by the Mahalanobis
          distance to the center.
      center : {float, int}, default None
          If a float, the value must be in [0, 1] and the center is center *
          nobs of the ordered data.  If an integer, must be in [0, nobs) and
          is interpreted as the observation of the ordered data to use.
  
      Returns
      -------
      fstat : float
          The test statistic based on the F test.
      pvalue : float
          The pvalue of the test.
  
      Notes
      -----
      This test assumes residuals are homoskedastic and may reject a correct
      linear specification if the residuals are heteroskedastic.
      """
      if not isinstance(res, RegressionResultsWrapper):
          raise TypeError(
              "res must be a results instance from a linear model."
          )
      frac = float_like(frac, "frac")
  
      use_distance = bool_like(use_distance, "use_distance")
      nobs = res.nobs
      endog = res.model.endog
      exog = res.model.exog
      if order_by is not None and use_distance:
          raise ValueError(
              "order_by and use_distance cannot be simultaneously"
              "used."
          )
      if order_by is not None:
          if isinstance(order_by, np.ndarray):
              order_by = array_like(
                  order_by, "order_by", ndim=1, dtype="int"
              )
          else:
              if isinstance(order_by, str):
                  order_by = [order_by]
              try:
                  cols = res.model.data.orig_exog[order_by].copy()
              except (IndexError, KeyError):
                  raise TypeError(
                      "order_by must contain valid column names "
                      "from the exog data used to construct res,"
                      "and exog must be a pandas DataFrame."
                  )
              name = "__index__"
              while name in cols:
                  name += "_"
              cols[name] = np.arange(cols.shape[0])
              cols = cols.sort_values(order_by)
              order_by = np.asarray(cols[name])
          endog = endog[order_by]
          exog = exog[order_by]
      if use_distance:
          center = int(nobs) // 2 if center is None else center
          if isinstance(center, float):
              if not 0.0 <= center <= 1.0:
                  raise ValueError(
                      "center must be in (0, 1) when a float."
                  )
              center = int(center * (nobs - 1))
          else:
              center = int_like(center, "center")
              if not 0 < center < nobs - 1:
                  raise ValueError(
                      "center must be in [0, nobs) when an int."
                  )
          center_obs = exog[center : center + 1]
          from scipy.spatial.distance import cdist
  
          try:
              err = exog - center_obs
              vi = np.linalg.inv(err.T @ err / nobs)
          except np.linalg.LinAlgError:
              err = exog - exog.mean(0)
              vi = np.linalg.inv(err.T @ err / nobs)
          dist = cdist(exog, center_obs, metric="mahalanobis", VI=vi)
          idx = np.argsort(dist.ravel())
          endog = endog[idx]
          exog = exog[idx]
  
      lowidx = np.ceil(0.5 * (1 - frac) * nobs).astype(int)
      uppidx = np.floor(lowidx + frac * nobs).astype(int)
      if uppidx - lowidx < exog.shape[1]:
          raise ValueError(
              "frac is too small to perform test. frac * nobs"
              "must be greater than the number of exogenous"
              "variables in the model."
          )
      mi_sl = slice(lowidx, uppidx)
      res_mi = OLS(endog[mi_sl], exog[mi_sl]).fit()
      nobs_mi = res_mi.model.endog.shape[0]
      ss_mi = res_mi.ssr
      ss = res.ssr
      fstat = (ss - ss_mi) / (nobs - nobs_mi) / ss_mi * res_mi.df_resid
      pval = stats.f.sf(fstat, nobs - nobs_mi, res_mi.df_resid)
      return fstat, pval
  
imports: from statsmodels.compat.pandas import deprecate_kwarg
  from collections.abc import Iterable
  import numpy
  import pandas
  from scipy import stats
  from statsmodels.regression.linear_model import OLS, RegressionResultsWrapper
  from statsmodels.stats._adnorm import anderson_statistic, normal_ad
  from statsmodels.stats._lilliefors import kstest_exponential, kstest_fit, kstest_normal, lilliefors
  from statsmodels.tools.validation import array_like, bool_like, dict_like, float_like, int_like, string_like
  from statsmodels.tsa.tsatools import lagmat
label_desc: Use image node_id 16 for calling a global function with example usage: linear_rainbow(res, frac, order_by, use_distance, center) and returns: fstat,  pval