docs: def posthoc_tukey(a, val_col = None, group_col = None, sort = False):
  
      '''Performs Tukey's all-pairs comparisons test for normally distributed data
      with equal group variances. For all-pairs comparisons in an
      one-factorial layout with normally distributed residuals and equal variances
      Tukey's test can be performed. A total of m = k(k-1)/2 hypotheses can be
      tested. The null hypothesis is tested in the two-tailed test against
      the alternative hypothesis [1]_, [2]_.
  
      Parameters
      ----------
      a : array_like or pandas DataFrame object
          An array, any object exposing the array interface or a pandas
          DataFrame.
  
      val_col : str, optional
          Name of a DataFrame column that contains dependent variable values (test
          or response variable). Values should have a non-nominal scale. Must be
          specified if `a` is a pandas DataFrame object.
  
      group_col : str, optional
          Name of a DataFrame column that contains independent variable values
          (grouping or predictor variable). Values should have a nominal scale
          (categorical). Must be specified if `a` is a pandas DataFrame object.
  
      sort : bool, optional
          If True, sort data by block and group columns.
  
      Returns
      -------
      result : pandas DataFrame
          P values.
  
      Notes
      -----
      The p values are computed from the Tukey-distribution.
  
      References
      ----------
      .. [1] L. Sachs (1997) Angewandte Statistik, New York: Springer.
      .. [2] J. Tukey (1949) Comparing Individual Means in the Analysis of Variance,
          Biometrics 5, 99-114.
  
      Examples
      --------
      >>> import scikit_posthocs as sp
      >>> import pandas as pd
      >>> x = pd.DataFrame({"a": [1,2,3,5,1], "b": [12,31,54,62,12], "c": [10,12,6,74,11]})
      >>> x = x.melt(var_name='groups', value_name='values')
      >>> sp.posthoc_tukey(x, val_col='values', group_col='groups')
  
      '''
  
      x, _val_col, _group_col = __convert_to_df(a, val_col, group_col)
  
      if not sort:
          x[_group_col] = Categorical(x[_group_col], categories=x[_group_col].unique(), ordered=True)
  
      x.sort_values(by=[_group_col], ascending=True, inplace=True)
      groups = np.unique(x[_group_col])
      x_grouped = x.groupby(_group_col)[_val_col]
  
      ni = x_grouped.count()
      n = ni.sum()
      xi = x_grouped.mean()
      si = x_grouped.var()
      sin = 1. / (n - groups.size) * np.sum(si * (ni - 1))
  
      def compare(i, j):
          dif = xi[i] - xi[j]
          A = sin * 0.5 * (1. / ni.loc[i] + 1. / ni.loc[j])
          q_val = dif / np.sqrt(A)
          return q_val
  
      vs = np.zeros((groups.size, groups.size), dtype=np.float)
      tri_upper = np.triu_indices(vs.shape[0], 1)
      tri_lower = np.tril_indices(vs.shape[0], -1)
      vs[:,:] = 0
  
      combs = it.combinations(range(groups.size), 2)
  
      for i,j in combs:
          vs[i, j] = compare(groups[i], groups[j])
  
      vs[tri_upper] = psturng(np.abs(vs[tri_upper]), groups.size, n - groups.size)
      vs[tri_lower] = vs.T[tri_lower]
  
      np.fill_diagonal(vs, -1)
      return DataFrame(vs, index=groups, columns=groups)