def cv_info(self): if self._cv_results is None: raise ValueError( f"CV: no cross-validation was performed. Use mu='auto' to perform cross-validation." ) cv_results = sorted(self._cv_results, key=attrgetter('mu')) criteria = ('cross-fit', 'l2/mu') best_mu = {criterion: self.cv_mu(criterion) for criterion in criteria} table = fmtxt.Table('lllll') table.cells('mu', 'cross-fit', 'l2-error', 'weighted l2-error', 'ES metric') table.midrule() fmt = '%.5f' for result in cv_results: table.cell(fmtxt.stat(result.mu, fmt=fmt)) star = 1 if result.mu is best_mu['cross-fit'] else 0 table.cell(fmtxt.stat(result.cross_fit, fmt, star, 1)) star = 1 if result.mu is best_mu['l2/mu'] else 0 table.cell(fmtxt.stat(result.l2_error, fmt, star, 1)) table.cell(fmtxt.stat(result.weighted_l2_error, fmt=fmt)) table.cell(fmtxt.stat(result.estimation_stability, fmt=fmt)) # warnings mus = [res.mu for res in self._cv_results] warnings = [] if self.mu == min(mus): warnings.append(f"Best mu is smallest mu") if warnings: table.caption(f"Warnings: {'; '.join(warnings)}") return table
def reduction_table(self, labels=None, vertical=False): """Table with steps of model reduction Parameters ---------- labels : dict {str: str} Substitute new labels for predictors. vertical : bool Orient table vertically. """ if not self._reduction_results: self.execute() if labels is None: labels = {} n_steps = len(self._reduction_results) # find terms terms = [] for ress in self._reduction_results: terms.extend(term for term in ress.keys() if term not in terms) n_terms = len(terms) # cell content cells = {} for x in terms: for i, ress in enumerate(self._reduction_results): if x in ress: res = ress[x] pmin = res.p.min() t_cell = fmtxt.stat(res.t.max(), stars=pmin) p_cell = fmtxt.p(pmin) else: t_cell = p_cell = '' cells[i, x] = t_cell, p_cell if vertical: t = fmtxt.Table('ll' + 'l' * n_terms) t.cells('Step', '') for x in terms: t.cell(labels.get(x, x)) t.midrule() for i in range(n_steps): t_row = t.add_row() p_row = t.add_row() t_row.cells(i + 1, fmtxt.symbol('t', 'max')) p_row.cells('', fmtxt.symbol('p')) for x in terms: t_cell, p_cell = cells[i, x] t_row.cell(t_cell) p_row.cell(p_cell) else: t = fmtxt.Table('l' + 'rr' * n_steps) t.cell() for _ in range(n_steps): t.cell(fmtxt.symbol('t', 'max')) t.cell(fmtxt.symbol('p')) t.midrule() for x in terms: t.cell(labels.get(x, x)) for i in range(n_steps): t.cells(*cells[i, x]) return t
def table(self, title=None, caption=None): """Table with effects and smallest p-value""" if self.test_type is LMGroup: cols = sorted( {col for res in self.values() for col in res.column_names}) table = fmtxt.Table('l' * (1 + len(cols)), title=title, caption=caption) table.cell('') table.cells(*cols) table.midrule() for key, lmg in self.items(): table.cell(key) for res in (lmg.tests[c] for c in cols): pmin = res.p.min() table.cell(fmtxt.FMText([fmtxt.p(pmin), star(pmin)])) elif self.test_type is anova: table = fmtxt.Table('lllll', title=title, caption=caption) table.cells('Test', 'Effect', fmtxt.symbol(self.test_type._statistic, 'max'), fmtxt.symbol('p'), 'sig') table.midrule() for key, res in self.items(): for i, effect in enumerate(res.effects): table.cells(key, effect) pmin = res.p[i].min() table.cell(fmtxt.stat(res._max_statistic(i))) table.cell(fmtxt.p(pmin)) table.cell(star(pmin)) key = '' else: table = fmtxt.Table('llll', title=title, caption=caption) table.cells('Effect', fmtxt.symbol(self.test_type._statistic, 'max'), fmtxt.symbol('p'), 'sig') table.midrule() for key, res in self.items(): table.cell(key) pmin = res.p.min() table.cell(fmtxt.stat(res._max_statistic())) table.cell(fmtxt.p(pmin)) table.cell(star(pmin)) return table
def clusters(self, p=0.05): """Table with significant clusters""" if self.test_type is TestType.TWO_STAGE: raise NotImplementedError else: table = fmtxt.Table('lrrrrll') table.cells('Effect', 't-start', 't-stop', fmtxt.symbol(self._statistic, 'max'), fmtxt.symbol('t', 'peak'), fmtxt.symbol('p'), 'sig', just='l') table.midrule() for key, res in self.items(): table.cell(key) table.endline() clusters = res.find_clusters(p, maps=True) clusters.sort('tstart') if self.test_type is not TestType.MULTI_EFFECT: clusters[:, 'effect'] = '' for effect, tstart, tstop, p_, sig, cmap in clusters.zip('effect', 'tstart', 'tstop', 'p', 'sig', 'cluster'): max_stat, max_time = res._max_statistic(mask=cmap != 0, return_time=True) table.cells(f' {effect}', ms(tstart), ms(tstop), fmtxt.stat(max_stat), ms(max_time), fmtxt.p(p_), sig) return table
def anova(self): "Return an ANOVA table" # table head table = fmtxt.Table("l" + "r" * 5) if self.title: table.title(self.title) table.cell() headers = ["SS", "df", "MS"] headers += ["F", "p"] for hd in headers: table.cell(hd, r"\textbf", just="c") table.midrule() # table body for name, F_test in zip(self.names, self.F_tests): table.cell(name) table.cell(fmtxt.stat(F_test.SS)) table.cell(fmtxt.stat(F_test.df, fmt="%i")) table.cell(fmtxt.stat(F_test.MS)) if F_test.F: stars = test.star(F_test.p) table.cell(fmtxt.stat(F_test.F, stars=stars)) table.cell(fmtxt.p(F_test.p)) else: table.cell() table.cell() # residuals if self.X.df_error > 0: table.empty_row() table.cell("Residuals") SS, df, MS = self.residuals table.cell(SS) table.cell(df, fmt="%i") table.cell(MS) table.endline() # total table.midrule() table.cell("Total") SS = np.sum((self.Y.x - self.Y.mean()) ** 2) table.cell(fmtxt.stat(SS)) table.cell(fmtxt.stat(len(self.Y) - 1, fmt="%i")) return table
def anova(self): "Return ANOVA table" if self.show_ems is None: ems = defaults["show_ems"] else: ems = self.show_ems # table head table = textab.Table("l" + "r" * (5 + ems)) if self.title: table.title(self.title) table.cell() headers = ["SS", "df", "MS"] # if ems: headers += ["E(MS)"] headers += ["F", "p"] for hd in headers: table.cell(hd, r"\textbf", just="c") table.midrule() # table body for name, SS, df, MS, F, p in self._results_table: table.cell(name) table.cell(textab.stat(SS)) table.cell(textab.stat(df, fmt="%i")) table.cell(textab.stat(MS)) if F: stars = test.star(p) table.cell(textab.stat(F, stars=stars)) table.cell(textab.p(p)) else: table.cell() table.cell() # total table.midrule() table.cell("Total") table.cell(textab.stat(self.Y.SS)) table.cell(textab.stat(self.Y.N - 1, fmt="%i")) return table