diff --git a/yli/regress.py b/yli/regress.py index 2b78bc6..1e89ccd 100644 --- a/yli/regress.py +++ b/yli/regress.py @@ -249,10 +249,10 @@ class RegressionResult: if html: right_col.append(('F:', format(f_result.statistic, '.2f'))) - right_col.append(('p (F):', fmt_p(f_result.pvalue, html=True, tabular=True))) + right_col.append(('p (F):', fmt_p(f_result.pvalue, html=True, only_value=True))) else: right_col.append(('F:', format(f_result.statistic, '.2f'))) - right_col.append(('p (F):', fmt_p(f_result.pvalue, html=False, tabular=True))) + right_col.append(('p (F):', fmt_p(f_result.pvalue, html=False, only_value=True))) else: # Otherwise report likelihood ratio test as overall test lrtest_result = self.lrtest_null() @@ -260,9 +260,9 @@ class RegressionResult: right_col.append(('LL-Model:', format(self.llf, '.2f'))) right_col.append(('LL-Null:', format(self.llnull, '.2f'))) if html: - right_col.append(('p (LR):', fmt_p(lrtest_result.pvalue, html=True, tabular=True))) + right_col.append(('p (LR):', fmt_p(lrtest_result.pvalue, html=True, only_value=True))) else: - right_col.append(('p (LR):', fmt_p(lrtest_result.pvalue, html=False, tabular=True))) + right_col.append(('p (LR):', fmt_p(lrtest_result.pvalue, html=False, only_value=True))) return left_col, right_col diff --git a/yli/utils.py b/yli/utils.py index fb40365..5887505 100644 --- a/yli/utils.py +++ b/yli/utils.py @@ -86,55 +86,79 @@ def do_fmt_p(p): # Nonsignificant: round up p = config.alpha + 10**-config.pvalue_max_dps - return None, '{0:.{dps}f}'.format(p, dps=config.pvalue_max_dps) + return '', '{0:.{dps}f}'.format(p, dps=config.pvalue_max_dps) if p < 10**-config.pvalue_min_dps: # Insufficient resolution at pvalue_min_dps # We know from earlier comparison that 1 s.f. fits within pvalue_max_dps - return None, '{:.1g}'.format(p) + return '', '{:.1g}'.format(p) # OK to round to pvalue_min_dps - return None, '{0:.{dps}f}'.format(p, dps=config.pvalue_min_dps) + return '', '{0:.{dps}f}'.format(p, dps=config.pvalue_min_dps) -def fmt_p(p, *, html, tabular=False): +def fmt_p(p, *, html, only_value=False, tabular=False): """ Format p value tabular: If true, output in ‘tabular’ format of p values where decimal points align """ + # FIXME: Make only_value and tabular enums + sign, fmt = do_fmt_p(p) # Strip leading zero if required if not config.pvalue_leading_zero: fmt = fmt.lstrip('0') - # Add significance asterisk if required + # Check if significant if p < config.alpha: - fmt += '*' - - if sign is not None: - if html: - # Escape angle quotes - sign = sign.replace('<', '<') - sign = sign.replace('>', '>') - - if tabular: - pfmt = sign + fmt # e.g. "<0.001" - else: - pfmt = sign + ' ' + fmt # e.g. "< 0.001" + asterisk = '*' else: - if tabular: - # Tabular format with no sign: add a preceding space to get decimal points to line up - if html: - # Insert space with width of '=' which should be width of '<' and '>' too - pfmt = '=' + fmt # e.g. "0.05" - else: - pfmt = ' ' + fmt # e.g. "0.05" - else: - pfmt = '= ' + fmt # e.g. "= 0.05" + asterisk = '' - return pfmt + if html: + # Escape angle quotes + sign = sign.replace('<', '<') + sign = sign.replace('>', '>') + + if only_value: + return '{}{}{}'.format(sign, fmt, asterisk) + elif tabular: + # Always left-aligned, so reserve space for sign if required to align decimal points + if not sign: + sign = '=' + + return '{}{}{}'.format(sign, fmt, asterisk) + else: + # Non-tabular so force a sign + if not sign: + sign = '=' + return '{} {}{}'.format(sign, fmt, asterisk) + else: + if only_value: + return '{}{}{}'.format(sign, fmt, asterisk) + elif tabular: + # Right-aligned, so add spaces to simulate left alignment + if not sign: + sign = ' ' + + # +1 for decimal point + # +1 for sign + # +1 for asterisk + pvalue_max_len = config.pvalue_max_dps + 3 + if config.pvalue_leading_zero: + pvalue_max_len += 1 + + # Now add spaces + rpadding = ' ' * (pvalue_max_len - len(sign + fmt + asterisk)) + + return '{}{}{}{}'.format(sign, fmt, asterisk, rpadding) + else: + # Non-tabular so force a sign + if not sign: + sign = '=' + return '{} {}{}'.format(sign, fmt, asterisk) # ------------------------------ # General result-related classes