docs: def sign_table(p_values, lower=True, upper=True):
      """
      Significance table
  
      Returns table that can be used in a publication. P values are replaced
      with asterisks: \* - p < 0.05, \*\* - p < 0.01, \*\*\* - p < 0.001.
  
      Parameters
      ----------
      p_values : array_like, or ndarray, or pandas DataFrame
          An array, any object exposing the array interface, containing
          p values.
  
      lower : bool, optional
          Defines whether to return the lower triangle.
  
      upper : bool, optional
          Defines whether to return the upper triangle.
  
      Returns
      -------
      Numpy array or pandas DataFrame with asterisks masked p values.
  
      Examples
      --------
  
      >>> p_values = np.array([[-1.        ,  0.00119517,  0.00278329],
                        [ 0.00119517, -1.        ,  0.18672227],
                        [ 0.00278329,  0.18672227, -1.        ]])
      >>> ph.sign_table(p_values)
      array([['-', '**', '**'],
             ['**', '-', 'NS'],
             ['**', 'NS', '-']], dtype=object)
  
      """
      if not any([lower, upper]):
          raise ValueError("Either lower or upper triangle must be returned")
  
      if not isinstance(p_values, DataFrame):
          p_values = np.array(p_values, dtype=np.float)
  
      ns = p_values > 0.05
      three = (p_values < 0.001) & (p_values >= 0)
      two = (p_values < 0.01) & (p_values >= 0.001)
      one = (p_values < 0.05) & (p_values >= 0.01)
  
      p_values = p_values.astype(object)
      p_values[ns] = 'NS'
      p_values[three] = '***'
      p_values[two] = '**'
      p_values[one] = '*'
  
      if not isinstance(p_values, DataFrame):
          np.fill_diagonal(p_values, '-')
          if not lower:
              p_values[np.tril_indices(p_values.shape[0], -1)] = ''
          elif not upper:
              p_values[np.triu_indices(p_values.shape[0], 1)] = ''
      else:
          np.fill_diagonal(p_values.values, '-')
          if not lower:
              p_values.values[np.tril_indices(p_values.shape[0], -1)] = ''
          elif not upper:
              p_values.values[np.triu_indices(p_values.shape[0], 1)] = ''
  
      return p_values