docs: def posthoc_conover_friedman(a, y_col=None, block_col=None, group_col=None, melted=False, sort=False, p_adjust=None):
  
      '''Calculate pairwise comparisons using Conover post hoc test for unreplicated
      blocked data. This test is usually conducted post hoc after
      significant results of the Friedman test. The statistics refer to
      the Student t distribution [1]_, [2]_.
  
      Parameters
      ----------
      a : array_like or pandas DataFrame object
          An array, any object exposing the array interface or a pandas
          DataFrame.
  
          If `melted` is set to False (default), `a` is a typical matrix of
          block design, i.e. rows are blocks, and columns are groups. In this
          case you do not need to specify col arguments.
  
          If `a` is an array and `melted` is set to True,
          y_col, block_col and group_col must specify the indices of columns
          containing elements of correspondary type.
  
          If `a` is a Pandas DataFrame and `melted` is set to True,
          y_col, block_col and group_col must specify columns names (strings).
  
      y_col : str or int
          Must be specified if `a` is a pandas DataFrame object.
          Name of the column that contains y data.
  
      block_col : str or int
          Must be specified if `a` is a pandas DataFrame object.
          Name of the column that contains blocking factor values.
  
      group_col : str or int
          Must be specified if `a` is a pandas DataFrame object.
          Name of the column that contains treatment (group) factor values.
  
      melted : bool, optional
          Specifies if data are given as melted columns "y", "blocks", and
          "groups".
  
      sort : bool, optional
          If True, sort data by block and group columns.
  
      p_adjust : str, optional
          Method for adjusting p values. See statsmodels.sandbox.stats.multicomp
          for details. Available methods are:
          'bonferroni' : one-step correction
          'sidak' : one-step correction
          'holm-sidak' : step-down method using Sidak adjustments
          'holm' : step-down method using Bonferroni adjustments
          'simes-hochberg' : step-up method  (independent)
          'hommel' : closed method based on Simes tests (non-negative)
          'fdr_bh' : Benjamini/Hochberg  (non-negative)
          'fdr_by' : Benjamini/Yekutieli (negative)
          'fdr_tsbh' : two stage fdr correction (non-negative)
          'fdr_tsbky' : two stage fdr correction (non-negative)
          'single-step' : uses Tukey distribution for multiple comparisons
  
      Returns
      -------
      result : pandas DataFrame
          P values.
  
      Notes
      -----
      A one-way ANOVA with repeated measures that is also referred to as ANOVA
      with unreplicated block design can also be conducted via the
      friedman.test. The consequent post hoc pairwise multiple comparison test
      according to Conover is conducted with this function.
  
      If y is a matrix, than the columns refer to the treatment and the rows
      indicate the block.
  
      References
      ----------
      .. [1] W. J. Conover and R. L. Iman (1979), On multiple-comparisons procedures,
          Tech. Rep. LA-7677-MS, Los Alamos Scientific Laboratory.
  
      .. [2] W. J. Conover (1999), Practical nonparametric Statistics, 3rd. Edition,
          Wiley.
  
      Examples
      --------
      >>> x = np.array([[31,27,24],[31,28,31],[45,29,46],[21,18,48],[42,36,46],[32,17,40]])
      >>> sp.posthoc_conover_friedman(x)
  
      '''
  
      if melted and not all([block_col, group_col, y_col]):
          raise ValueError('block_col, group_col, y_col should be explicitly specified if using melted data')
  
      def compare_stats(i, j):
          dif = np.abs(R.loc[groups[i]] - R.loc[groups[j]])
          tval = dif / np.sqrt(A) / np.sqrt(B)
          pval = 2. * ss.t.sf(np.abs(tval), df = (m*n*k - k - n + 1))
          return pval
  
      def compare_tukey(i, j):
          dif = np.abs(R.loc[groups[i]] - R.loc[groups[j]])
          qval = np.sqrt(2.) * dif / (np.sqrt(A) * np.sqrt(B))
          pval = psturng(qval, k, np.inf)
          return pval
  
      x, _y_col, _group_col, _block_col = __convert_to_block_df(a, y_col, group_col, block_col, melted)
  
      #if not sort:
      #    x[group_col] = Categorical(x[group_col], categories=x[group_col].unique(), ordered=True)
      #    x[block_col] = Categorical(x[block_col], categories=x[block_col].unique(), ordered=True)
      x.sort_values(by=[_group_col,_block_col], ascending=True, inplace=True)
      x.dropna(inplace=True)
  
      groups = np.unique(x[_group_col])
      k = groups.size
      n = x[_block_col].unique().size
  
      x['mat'] = x.groupby(_block_col)[_y_col].rank()
      R = x.groupby(_group_col)['mat'].sum()
      A1 = (x['mat'] ** 2).sum()
      m = 1
      S2 = m/(m*k - 1.) * (A1 - m*k*n*(m*k + 1.)**2./4.)
      T2 = 1 / S2 * (np.sum(R) - n * m * ((m * k + 1.) / 2.)**2.)
      A = S2 * (2. * n * (m * k - 1.)) / ( m * n * k - k - n + 1.)
      B = 1. - T2 / (n * (m * k - 1.))
  
      vs = np.zeros((k, k))
      combs = it.combinations(range(k), 2)
  
      tri_upper = np.triu_indices(vs.shape[0], 1)
      tri_lower = np.tril_indices(vs.shape[0], -1)
      vs[:,:] = 0
  
      if p_adjust == 'single-step':
          for i, j in combs:
              vs[i, j] = compare_tukey(i, j)
      else:
          for i, j in combs:
              vs[i, j] = compare_stats(i, j)
  
          if p_adjust is not None:
              vs[tri_upper] = multipletests(vs[tri_upper], method = p_adjust)[1]
  
      vs[tri_lower] = vs.T[tri_lower]
      np.fill_diagonal(vs, -1)
      return DataFrame(vs, index=groups, columns=groups)