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