diff --git a/mlair/plotting/postprocessing_plotting.py b/mlair/plotting/postprocessing_plotting.py index b23807ae30f52f19581b188d19213fdc81c9258e..afbd00d0e84f1478c3b43bc57af19752e05eefef 100644 --- a/mlair/plotting/postprocessing_plotting.py +++ b/mlair/plotting/postprocessing_plotting.py @@ -1112,7 +1112,7 @@ class PlotSampleUncertaintyFromBootstrap(AbstractPlotClass): # pragma: no cover self.prepare_data(data) # create all combinations to plot (h/v, utest/notest, single/multi) - variants = list(itertools.product(*[["v", "h"], [True, False], ["single", "multi"]])) + variants = list(itertools.product(*[["v", "h"], [True, False], ["single", "multi", "panel"]])) # plot raw metric (mse) for orientation, utest, agg_type in variants: @@ -1157,7 +1157,9 @@ class PlotSampleUncertaintyFromBootstrap(AbstractPlotClass): # pragma: no cover if apply_u_test is True and agg_type == "multi": return # not implemented data_table = self._data_table - if self.ahead_dim not in data_table.index.names and agg_type == "multi": + if self.ahead_dim not in data_table.index.names and agg_type in ["multi", "panel"]: + return # nothing to do + if apply_u_test is True and agg_type == "panel": return # nothing to do n_boots = self._n_boots size = len(np.unique(data_table.columns)) @@ -1177,7 +1179,7 @@ class PlotSampleUncertaintyFromBootstrap(AbstractPlotClass): # pragma: no cover showmeans=True, meanprops={"markersize": 6, "markeredgecolor": "k"}, flierprops={"marker": "o", "markerfacecolor": "black", "markeredgecolor": "none", "markersize": 3}, boxprops={'facecolor': 'none', 'edgecolor': 'k'}, width=width, orient=orientation) - else: + elif agg_type == "multi": xy = {"x": self.model_type_dim, "y": 0} if orientation == "v" else {"x": 0, "y": self.model_type_dim} sns.boxplot(data=data_table.stack(self.model_type_dim).reset_index(), ax=ax, whis=1.5, palette=color_palette, showmeans=True, meanprops={"markersize": 6, "markeredgecolor": "k", "markerfacecolor": "white"}, @@ -1187,33 +1189,68 @@ class PlotSampleUncertaintyFromBootstrap(AbstractPlotClass): # pragma: no cover _labels = [str(i) + self.sampling for i in data_table.index.levels[1].values] handles, _ = ax.get_legend_handles_labels() ax.legend(handles, _labels) + else: + xy = (self.model_type_dim, 0) if orientation == "v" else (0, self.model_type_dim) + col_or_row = {"col": self.ahead_dim} if orientation == "v" else {"row": self.ahead_dim} + aspect = 0.4 if orientation == "v" else 5./3. + ax = sns.FacetGrid(data_table.stack(self.model_type_dim).reset_index(), **col_or_row, aspect=aspect, height=5) + ax.map(sns.boxplot, *xy, whis=1.5, color="white", showmeans=True, order=data_table.mean().index.to_list(), + meanprops={"markersize": 6, "markeredgecolor": "k"}, + flierprops={"marker": "o", "markerfacecolor": "black", "markeredgecolor": "none", "markersize": 3}, + boxprops={'facecolor': 'none', 'edgecolor': 'k'}, width=width, orient=orientation) - if orientation == "v": - if apply_u_test: - ax = self.set_significance_bars(asteriks, ax, data_table, orientation) - ylims = list(ax.get_ylim()) - ax.set_ylim([ylims[0], ylims[1]*1.025]) - ax.set_ylabel(f"{self.error_measure} (in {self.error_unit})") - ax.set_xticklabels(ax.get_xticklabels(), rotation=45) - elif orientation == "h": - if apply_u_test: - ax = self.set_significance_bars(asteriks, ax, data_table, orientation) - ax.set_xlabel(f"{self.error_measure} (in {self.error_unit})") - xlims = list(ax.get_xlim()) - ax.set_xlim([xlims[0], xlims[1] * 1.015]) + _labels = [str(i) + self.sampling for i in data_table.index.levels[1].values] + for axi, title in zip(ax.axes.flatten(), _labels): + axi.set_title(title) + plt.setp(axi.lines, color='k') + + if agg_type == "panel": + if orientation == "v": + for axi in ax.axes.flatten(): + axi.set_xlabel(None) + axi.set_xticklabels(axi.get_xticklabels(), rotation=45) + ax.set_ylabels(f"{self.error_measure} (in {self.error_unit})") + loc = "upper left" + else: + for axi in ax.axes.flatten(): + axi.set_ylabel(None) + ax.set_xlabels(f"{self.error_measure} (in {self.error_unit})") + loc = "upper right" + text = f"n={n_boots}" + if self.block_length is not None: + text = f"{self.block_length}, {text}" + if len(season) > 0: + text = f"{season}, {text}" + text_box = AnchoredText(text, frameon=True, loc=loc) + plt.setp(text_box.patch, edgecolor='k', facecolor='w') + ax.axes.flatten()[0].add_artist(text_box) else: - raise ValueError(f"orientation must be `v' or `h' but is: {orientation}") - text = f"n={n_boots}" - if self.block_length is not None: - text = f"{self.block_length}, {text}" - if len(season) > 0: - text = f"{season}, {text}" - loc = "lower left" - text_box = AnchoredText(text, frameon=True, loc=loc, pad=0.5, bbox_to_anchor=(0., 1.0), - bbox_transform=ax.transAxes) - plt.setp(text_box.patch, edgecolor='k', facecolor='w') - ax.add_artist(text_box) - plt.setp(ax.lines, color='k') + if orientation == "v": + if apply_u_test: + ax = self.set_significance_bars(asteriks, ax, data_table, orientation) + ylims = list(ax.get_ylim()) + ax.set_ylim([ylims[0], ylims[1]*1.025]) + ax.set_ylabel(f"{self.error_measure} (in {self.error_unit})") + ax.set_xticklabels(ax.get_xticklabels(), rotation=45) + elif orientation == "h": + if apply_u_test: + ax = self.set_significance_bars(asteriks, ax, data_table, orientation) + ax.set_xlabel(f"{self.error_measure} (in {self.error_unit})") + xlims = list(ax.get_xlim()) + ax.set_xlim([xlims[0], xlims[1] * 1.015]) + else: + raise ValueError(f"orientation must be `v' or `h' but is: {orientation}") + text = f"n={n_boots}" + if self.block_length is not None: + text = f"{self.block_length}, {text}" + if len(season) > 0: + text = f"{season}, {text}" + loc = "lower left" + text_box = AnchoredText(text, frameon=True, loc=loc, pad=0.5, bbox_to_anchor=(0., 1.0), + bbox_transform=ax.transAxes) + plt.setp(text_box.patch, edgecolor='k', facecolor='w') + ax.add_artist(text_box) + plt.setp(ax.lines, color='k') plt.tight_layout() self._save() plt.close("all")