#1433 Add support for discrete variables in rank plots

Merged Osvaldo Martin aloctavodia
Coverage Reach
plots/backends/matplotlib/forestplot.py plots/backends/matplotlib/ppcplot.py plots/backends/matplotlib/pairplot.py plots/backends/matplotlib/traceplot.py plots/backends/matplotlib/khatplot.py plots/backends/matplotlib/posteriorplot.py plots/backends/matplotlib/bpvplot.py plots/backends/matplotlib/elpdplot.py plots/backends/matplotlib/essplot.py plots/backends/matplotlib/mcseplot.py plots/backends/matplotlib/kdeplot.py plots/backends/matplotlib/loopitplot.py plots/backends/matplotlib/violinplot.py plots/backends/matplotlib/rankplot.py plots/backends/matplotlib/densityplot.py plots/backends/matplotlib/distplot.py plots/backends/matplotlib/__init__.py plots/backends/matplotlib/distcomparisonplot.py plots/backends/matplotlib/jointplot.py plots/backends/matplotlib/energyplot.py plots/backends/matplotlib/compareplot.py plots/backends/matplotlib/separationplot.py plots/backends/matplotlib/autocorrplot.py plots/backends/matplotlib/parallelplot.py plots/backends/matplotlib/hdiplot.py plots/backends/bokeh/forestplot.py plots/backends/bokeh/pairplot.py plots/backends/bokeh/traceplot.py plots/backends/bokeh/kdeplot.py plots/backends/bokeh/ppcplot.py plots/backends/bokeh/posteriorplot.py plots/backends/bokeh/bpvplot.py plots/backends/bokeh/elpdplot.py plots/backends/bokeh/densityplot.py plots/backends/bokeh/violinplot.py plots/backends/bokeh/rankplot.py plots/backends/bokeh/__init__.py plots/backends/bokeh/loopitplot.py plots/backends/bokeh/mcseplot.py plots/backends/bokeh/essplot.py plots/backends/bokeh/khatplot.py plots/backends/bokeh/distplot.py plots/backends/bokeh/energyplot.py plots/backends/bokeh/compareplot.py plots/backends/bokeh/jointplot.py plots/backends/bokeh/separationplot.py plots/backends/bokeh/autocorrplot.py plots/backends/bokeh/parallelplot.py plots/backends/bokeh/hdiplot.py plots/backends/bokeh/distcomparisonplot.py plots/backends/__init__.py plots/plot_utils.py plots/ppcplot.py plots/hdiplot.py plots/densityplot.py plots/essplot.py plots/bpvplot.py plots/pairplot.py plots/loopitplot.py plots/traceplot.py plots/parallelplot.py plots/distcomparisonplot.py plots/elpdplot.py plots/separationplot.py plots/khatplot.py plots/forestplot.py plots/kdeplot.py plots/posteriorplot.py plots/mcseplot.py plots/rankplot.py plots/jointplot.py plots/__init__.py plots/violinplot.py plots/compareplot.py plots/distplot.py plots/autocorrplot.py plots/energyplot.py data/inference_data.py data/io_pystan.py data/io_cmdstan.py data/io_pymc3.py data/io_cmdstanpy.py data/io_pyro.py data/io_numpyro.py data/base.py data/io_dict.py data/io_emcee.py data/io_tfp.py data/io_pyjags.py data/converters.py data/datasets.py data/__init__.py data/io_json.py data/io_netcdf.py stats/stats.py stats/diagnostics.py stats/density_utils.py stats/stats_utils.py stats/stats_refitting.py stats/__init__.py utils.py rcparams.py wrappers/base.py wrappers/wrap_pystan.py wrappers/__init__.py

No flags found

Use flags to group coverage reports by test type, project and/or folders.
Then setup custom commit statuses and notifications for each flag.

e.g., #unittest #integration

#production #enterprise

#frontend #backend

Learn more about Codecov Flags here.


@@ -1,12 +1,12 @@
Loading
1 1
"""Bokeh rankplot."""
2 2
import numpy as np
3 -
import scipy.stats
3 +
4 4
from bokeh.models import Span
5 5
from bokeh.models.annotations import Title
6 6
from bokeh.models.tickers import FixedTicker
7 7
8 8
from ....stats.density_utils import histogram
9 -
from ...plot_utils import _scale_fig_size, make_label
9 +
from ...plot_utils import _scale_fig_size, make_label, compute_ranks
10 10
from .. import show_layout
11 11
from . import backend_kwarg_defaults, create_axes_grid
12 12
@@ -74,7 +74,7 @@
Loading
74 74
    for ax, (var_name, selection, var_data) in zip(
75 75
        (item for item in axes.flatten() if item is not None), plotters
76 76
    ):
77 -
        ranks = scipy.stats.rankdata(var_data, method="average").reshape(var_data.shape)
77 +
        ranks = compute_ranks(var_data)
78 78
        bin_ary = np.histogram_bin_edges(ranks, bins=bins, range=(0, ranks.size))
79 79
        all_counts = np.empty((len(ranks), len(bin_ary) - 1))
80 80
        for idx, row in enumerate(ranks):

@@ -1,10 +1,9 @@
Loading
1 1
"""Matplotlib rankplot."""
2 2
import matplotlib.pyplot as plt
3 3
import numpy as np
4 -
import scipy.stats
5 4
6 5
from ....stats.density_utils import histogram
7 -
from ...plot_utils import _scale_fig_size, make_label
6 +
from ...plot_utils import _scale_fig_size, make_label, compute_ranks
8 7
from . import backend_kwarg_defaults, backend_show, create_axes_grid
9 8
10 9
@@ -66,7 +65,7 @@
Loading
66 65
        )
67 66
68 67
    for ax, (var_name, selection, var_data) in zip(np.ravel(axes), plotters):
69 -
        ranks = scipy.stats.rankdata(var_data, method="average").reshape(var_data.shape)
68 +
        ranks = compute_ranks(var_data)
70 69
        bin_ary = np.histogram_bin_edges(ranks, bins=bins, range=(0, ranks.size))
71 70
        all_counts = np.empty((len(ranks), len(bin_ary) - 1))
72 71
        for idx, row in enumerate(ranks):

@@ -9,7 +9,9 @@
Loading
9 9
import packaging
10 10
import xarray as xr
11 11
from matplotlib.colors import to_hex
12 -
from scipy.stats import mode
12 +
from scipy.stats import mode, rankdata
13 +
from scipy.interpolate import CubicSpline
14 +
13 15
14 16
from ..rcparams import rcParams
15 17
from ..stats.density_utils import kde
@@ -659,3 +661,17 @@
Loading
659 661
    )
660 662
661 663
    return ax
664 +
665 +
666 +
def compute_ranks(ary):
667 +
    """Compute ranks for continuos and discrete variables."""
668 +
    if ary.dtype.kind == "i":
669 +
        ary_shape = ary.shape
670 +
        ary = ary.flatten()
671 +
        min_ary, max_ary = min(ary), max(ary)
672 +
        x = np.linspace(min_ary, max_ary, len(ary))
673 +
        csi = CubicSpline(x, ary)
674 +
        ary = csi(np.linspace(min_ary + 0.001, max_ary - 0.001, len(ary))).reshape(ary_shape)
675 +
    ranks = rankdata(ary, method="average").reshape(ary.shape)
676 +
677 +
    return ranks

Everything is accounted for!

No changes detected that need to be reviewed.
What changes does Codecov check for?
Lines, not adjusted in diff, that have changed coverage data.
Files that introduced coverage data that had none before.
Files that have missing coverage data that once were tracked.
Files Coverage
arviz 0.01% 91.92%
Project Totals (105 files) 91.92%
Loading