code: def multivariate_ttest(X, Y=None, paired=False):
      """Hotelling T-squared test (= multivariate T-test)
  
      Parameters
      ----------
      X : np.array
          First data matrix of shape (n_samples, n_features).
      Y : np.array or None
          Second data matrix of shape (n_samples, n_features). If ``Y`` is a 1D
          array of shape (n_features), a one-sample test is performed where the
          null hypothesis is defined in ``Y``. If ``Y`` is None, a one-sample
          is performed against np.zeros(n_features).
      paired : boolean
          Specify whether the two observations are related (i.e. repeated
          measures) or independent. If ``paired`` is True, ``X`` and ``Y`` must
          have exactly the same shape.
  
      Returns
      -------
      stats : :py:class:`pandas.DataFrame`
  
          * ``'T2'``: T-squared value
          * ``'F'``: F-value
          * ``'df1'``: first degree of freedom
          * ``'df2'``: second degree of freedom
          * ``'p-val'``: p-value
  
      See Also
      --------
      multivariate_normality : Multivariate normality test.
      ttest : Univariate T-test.
  
      Notes
      -----
      The Hotelling 's T-squared test [1]_ is the multivariate counterpart of
      the T-test.
  
      Rows with missing values are automatically removed using the
      :py:func:`remove_na` function.
  
      Tested against the `Hotelling
      <https://cran.r-project.org/web/packages/Hotelling/Hotelling.pdf>`_ R
      package.
  
      References
      ----------
      .. [1] Hotelling, H. The Generalization of Student's Ratio. Ann. Math.
             Statist. 2 (1931), no. 3, 360--378.
  
      See also http://www.real-statistics.com/multivariate-statistics/
  
      Examples
      --------
      Two-sample independent Hotelling T-squared test
  
      >>> import pingouin as pg
      >>> data = pg.read_dataset('multivariate')
      >>> dvs = ['Fever', 'Pressure', 'Aches']
      >>> X = data[data['Condition'] == 'Drug'][dvs]
      >>> Y = data[data['Condition'] == 'Placebo'][dvs]
      >>> pg.multivariate_ttest(X, Y)
                       T2         F  df1  df2      pval
      hotelling  4.228679  1.326644    3   32  0.282898
  
      Two-sample paired Hotelling T-squared test
  
      >>> pg.multivariate_ttest(X, Y, paired=True)
                       T2         F  df1  df2      pval
      hotelling  4.468456  1.314252    3   15  0.306542
  
      One-sample Hotelling T-squared test with a specified null hypothesis
  
      >>> null_hypothesis_means = [37.5, 70, 5]
      >>> pg.multivariate_ttest(X, Y=null_hypothesis_means)
                         T2          F  df1  df2          pval
      hotelling  253.230991  74.479703    3   15  3.081281e-09
      """
      from scipy.stats import f
  
      x = np.asarray(X)
      assert x.ndim == 2, "x must be of shape (n_samples, n_features)"
  
      if Y is None:
          y = np.zeros(x.shape[1])
          # Remove rows with missing values in x
          x = x[~np.isnan(x).any(axis=1)]
      else:
          nx, kx = x.shape
          y = np.asarray(Y)
          assert y.ndim in [1, 2], "Y must be 1D or 2D."
          if y.ndim == 1:
              # One sample with specified null
              assert y.size == kx
          else:
              # Two-sample
              err = "X and Y must have the same number of features (= columns)."
              assert y.shape[1] == kx, err
              if paired:
                  err = "X and Y must have the same number of rows if paired."
                  assert y.shape[0] == nx, err
          # Remove rows with missing values in both x and y
          x, y = remove_na(x, y, paired=paired, axis="rows")
  
      # Shape of arrays
      nx, k = x.shape
      ny = y.shape[0]
      assert nx >= 5, "At least five samples are required."
  
      if y.ndim == 1 or paired is True:
          n = nx
          if y.ndim == 1:
              # One sample test
              cov = np.cov(x, rowvar=False)
              diff = x.mean(0) - y
          else:
              # Paired two sample
              cov = np.cov(x - y, rowvar=False)
              diff = x.mean(0) - y.mean(0)
          inv_cov = np.linalg.pinv(cov, hermitian=True)
          t2 = (diff @ inv_cov) @ diff * n
      else:
          n = nx + ny - 1
          x_cov = np.cov(x, rowvar=False)
          y_cov = np.cov(y, rowvar=False)
          pooled_cov = ((nx - 1) * x_cov + (ny - 1) * y_cov) / (n - 1)
          inv_cov = np.linalg.pinv(
              (1 / nx + 1 / ny) * pooled_cov, hermitian=True
          )
          diff = x.mean(0) - y.mean(0)
          t2 = (diff @ inv_cov) @ diff
  
      # F-value, degrees of freedom and p-value
      fval = t2 * (n - k) / (k * (n - 1))
      df1 = k
      df2 = n - k
      pval = f.sf(fval, df1, df2)
  
      # Create output dictionnary
      stats = {
          "T2": t2,
          "F": fval,
          "df1": df1,
          "df2": df2,
          "pval": pval,
      }
      stats = pd.DataFrame(stats, index=["hotelling"])
      return _postprocess_dataframe(stats)
  
imports: import numpy
  import pandas
  from collections import namedtuple
  from pingouin.utils import remove_na, _postprocess_dataframe
label_desc: Use image node_id 2 for calling a global function with example usage: multivariate_ttest(X, Y, paired) and returns: _postprocess_dataframe