Refactor fmt_p

This commit is contained in:
RunasSudo 2022-10-14 14:48:26 +11:00
parent 526d361338
commit 255ad100fd
Signed by: RunasSudo
GPG Key ID: 7234E476BF21C61A
3 changed files with 32 additions and 33 deletions

View File

@ -27,7 +27,7 @@ from datetime import datetime
import itertools
from .bayes_factors import BayesFactor, bayesfactor_afbf
from .utils import Estimate, check_nan, fmt_p_html, fmt_p_text
from .utils import Estimate, check_nan, fmt_p
def vif(df, formula=None, nan_policy='warn'):
"""
@ -86,10 +86,10 @@ class LikelihoodRatioTestResult:
self.pvalue = pvalue
def _repr_html_(self):
return 'LR({}) = {:.2f}; <i>p</i> {}'.format(self.dof, self.statistic, fmt_p_html(self.pvalue))
return 'LR({}) = {:.2f}; <i>p</i> {}'.format(self.dof, self.statistic, fmt_p(self.pvalue, html=True))
def summary(self):
return 'LR({}) = {:.2f}; p {}'.format(self.dof, self.statistic, fmt_p_text(self.pvalue))
return 'LR({}) = {:.2f}; p {}'.format(self.dof, self.statistic, fmt_p(self.pvalue, html=False))
class FTestResult:
"""Result of an F test for regression"""
@ -101,10 +101,10 @@ class FTestResult:
self.pvalue = pvalue
def _repr_html_(self):
return '<i>F</i>({}, {}) = {:.2f}; <i>p</i> {}'.format(self.dof_model, self.dof_resid, self.statistic, fmt_p_html(self.pvalue))
return '<i>F</i>({}, {}) = {:.2f}; <i>p</i> {}'.format(self.dof_model, self.dof_resid, self.statistic, fmt_p(self.pvalue, html=True))
def summary(self):
return 'F({}, {}) = {:.2f}; p {}'.format(self.dof_model, self.dof_resid, self.statistic, fmt_p_text(self.pvalue))
return 'F({}, {}) = {:.2f}; p {}'.format(self.dof_model, self.dof_resid, self.statistic, fmt_p(self.pvalue, html=False))
class RegressionResult:
"""
@ -220,10 +220,10 @@ class RegressionResult:
if html:
right_col.append(('<i>F</i>:', format(f_result.statistic, '.2f')))
right_col.append(('<i>p</i> (<i>F</i>):', fmt_p_html(f_result.pvalue, True)))
right_col.append(('<i>p</i> (<i>F</i>):', fmt_p(f_result.pvalue, html=True, nospace=True)))
else:
right_col.append(('F:', format(f_result.statistic, '.2f')))
right_col.append(('p (F):', fmt_p_text(f_result.pvalue, True)))
right_col.append(('p (F):', fmt_p(f_result.pvalue, html=False, nospace=True)))
else:
# Otherwise report likelihood ratio test as overall test
lrtest_result = self.lrtest_null()
@ -231,9 +231,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(('<i>p</i> (LR):', fmt_p_html(lrtest_result.pvalue, True)))
right_col.append(('<i>p</i> (LR):', fmt_p(lrtest_result.pvalue, html=True, nospace=True)))
else:
right_col.append(('p (LR):', fmt_p_text(lrtest_result.pvalue, True)))
right_col.append(('p (LR):', fmt_p(lrtest_result.pvalue, html=False, nospace=True)))
return left_col, right_col
@ -259,7 +259,7 @@ class RegressionResult:
if self.exp:
beta = np.exp(beta)
out += '<tr><th>{}</th><td>{:.2f}</td><td style="padding-right:0">({:.2f}</td><td>–</td><td style="padding-left:0">{:.2f})</td><td style="text-align:left">{}</td></tr>'.format(term, beta.point, beta.ci_lower, beta.ci_upper, fmt_p_html(self.pvalues[term], True))
out += '<tr><th>{}</th><td>{:.2f}</td><td style="padding-right:0">({:.2f}</td><td>–</td><td style="padding-left:0">{:.2f})</td><td style="text-align:left">{}</td></tr>'.format(term, beta.point, beta.ci_lower, beta.ci_upper, fmt_p(self.pvalues[term], html=True, nospace=True))
out += '</table>'
@ -293,7 +293,7 @@ class RegressionResult:
beta = np.exp(estimate)
# Add some extra padding
table_data.append([term + ' ', format(beta.point, '.2f'), '({:.2f}'.format(beta.ci_lower), '-', '{:.2f})'.format(beta.ci_upper), ' ' + fmt_p_text(self.pvalues[term], True)])
table_data.append([term + ' ', format(beta.point, '.2f'), '({:.2f}'.format(beta.ci_lower), '-', '{:.2f})'.format(beta.ci_upper), ' ' + fmt_p(self.pvalues[term], html=False, nospace=True)])
table2 = SimpleTable(data=table_data, headers=['', 'exp(β)' if self.exp else 'β', '', '\ue000', '', ' p']) # U+E000 is in Private Use Area, mark middle of CI column
table2_text = table2.as_text().replace(' \ue000 ', '(95% CI)') # Render heading in the right spot

View File

@ -22,7 +22,7 @@ import statsmodels.api as sm
import functools
import warnings
from .utils import Estimate, as_2groups, check_nan, fmt_p_html, fmt_p_text
from .utils import Estimate, as_2groups, check_nan, fmt_p
# ----------------
# Student's t test
@ -42,10 +42,10 @@ class TTestResult:
self.delta_direction = delta_direction
def _repr_html_(self):
return '<i>t</i>({:.0f}) = {:.2f}; <i>p</i> {}<br><i>δ</i> (95% CI) = {}, {}'.format(self.dof, self.statistic, fmt_p_html(self.pvalue), self.delta.summary(), self.delta_direction)
return '<i>t</i>({:.0f}) = {:.2f}; <i>p</i> {}<br><i>δ</i> (95% CI) = {}, {}'.format(self.dof, self.statistic, fmt_p(self.pvalue, html=True), self.delta.summary(), self.delta_direction)
def summary(self):
return 't({:.0f}) = {:.2f}; p {}\nδ (95% CI) = {}, {}'.format(self.dof, self.statistic, fmt_p_text(self.pvalue), self.delta.summary(), self.delta_direction)
return 't({:.0f}) = {:.2f}; p {}\nδ (95% CI) = {}, {}'.format(self.dof, self.statistic, fmt_p(self.pvalue, html=False), self.delta.summary(), self.delta_direction)
def ttest_ind(df, dep, ind, *, nan_policy='warn'):
"""Perform an independent-sample Student's t test"""
@ -91,14 +91,14 @@ class MannWhitneyResult:
self.brunnermunzel = brunnermunzel
def _repr_html_(self):
line1 = '<i>U</i> = {:.1f}; <i>p</i> {}<br><i>r</i> = {:.2f}, {}'.format(self.statistic, fmt_p_html(self.pvalue), self.rank_biserial, self.direction)
line1 = '<i>U</i> = {:.1f}; <i>p</i> {}<br><i>r</i> = {:.2f}, {}'.format(self.statistic, fmt_p(self.pvalue, html=True), self.rank_biserial, self.direction)
if self.brunnermunzel:
return line1 + '<br>' + self.brunnermunzel._repr_html_()
else:
return line1
def summary(self):
line1 = 'U = {:.1f}; p {}\nr = {}, {}'.format(self.statistic, fmt_p_text(self.pvalue), self.rank_biserial, self.direction)
line1 = 'U = {:.1f}; p {}\nr = {}, {}'.format(self.statistic, fmt_p(self.pvalue, html=False), self.rank_biserial, self.direction)
if self.brunnermunzel:
return line1 + '\n' + self.brunnermunzel.summary()
else:
@ -112,10 +112,10 @@ class BrunnerMunzelResult:
self.pvalue = pvalue
def _repr_html_(self):
return '<i>W</i> = {:.1f}; <i>p</i> {}'.format(self.statistic, fmt_p_html(self.pvalue))
return '<i>W</i> = {:.1f}; <i>p</i> {}'.format(self.statistic, fmt_p(self.pvalue, html=True))
def summary(self):
return 'W = {:.1f}; p {}'.format(self.statistic, fmt_p_text(self.pvalue))
return 'W = {:.1f}; p {}'.format(self.statistic, fmt_p(self.pvalue, html=False))
def mannwhitney(df, dep, ind, *, nan_policy='warn', brunnermunzel=True, use_continuity=False, alternative='two-sided', method='auto'):
"""
@ -174,18 +174,18 @@ class PearsonChiSquaredResult:
def _repr_html_(self):
if self.oddsratio is not None:
return '{}<br><i>χ</i><sup>2</sup>({}) = {:.2f}; <i>p</i> {}<br>OR (95% CI) = {}<br>RR (95% CI) = {}'.format(
self.ct._repr_html_(), self.dof, self.statistic, fmt_p_html(self.pvalue), self.oddsratio.summary(), self.riskratio.summary())
self.ct._repr_html_(), self.dof, self.statistic, fmt_p(self.pvalue, html=True), self.oddsratio.summary(), self.riskratio.summary())
else:
return '{}<br><i>χ</i><sup>2</sup>({}) = {:.2f}; <i>p</i> {}'.format(
self.ct._repr_html_(), self.dof, self.statistic, fmt_p_html(self.pvalue))
self.ct._repr_html_(), self.dof, self.statistic, fmt_p(self.pvalue, html=True))
def summary(self):
if self.oddsratio is not None:
return '{}\nχ²({}) = {:.2f}; p {}\nOR (95% CI) = {}\nRR (95% CI) = {}'.format(
self.ct, self.dof, self.statistic, fmt_p_text(self.pvalue), self.oddsratio.summary(), self.riskratio.summary())
self.ct, self.dof, self.statistic, fmt_p(self.pvalue, html=False), self.oddsratio.summary(), self.riskratio.summary())
else:
return '{}\nχ²({}) = {:.2f}; p {}'.format(
self.ct, self.dof, self.statistic, fmt_p_text(self.pvalue))
self.ct, self.dof, self.statistic, fmt_p(self.pvalue, html=False))
def chi2(df, dep, ind, *, nan_policy='warn'):
"""

View File

@ -71,26 +71,25 @@ def do_fmt_p(p):
else:
return None, '{:.1f}'.format(p)
def fmt_p_text(p, nospace=False):
"""Format p value for plaintext"""
def fmt_p(p, *, html, nospace=False):
"""Format p value"""
sign, fmt = do_fmt_p(p)
if sign is not None:
if nospace:
return sign + fmt # e.g. "<0.001"
pfmt = sign + fmt # e.g. "<0.001"
else:
return sign + ' ' + fmt # e.g. "< 0.001"
pfmt = sign + ' ' + fmt # e.g. "< 0.001"
else:
if nospace:
return fmt # e.g. "0.05"
pfmt = fmt # e.g. "0.05"
else:
return '= ' + fmt # e.g. "= 0.05"
def fmt_p_html(p, nospace=False):
"""Format p value for HTML"""
pfmt = '= ' + fmt # e.g. "= 0.05"
txt = fmt_p_text(p, nospace)
return txt.replace('<', '&lt;')
if html:
pfmt = pfmt.replace('<', '&lt;')
return pfmt
class Estimate:
"""A point estimate and surrounding confidence interval"""