Skip to content

Commit 0b14c03

Browse files
authoredJan 8, 2019
KDE: Display quantiles (arviz-devs#479)
* display quartiles * use where * compute quantiles from kde * remove unused variable * add test and example
1 parent 3fd200a commit 0b14c03

File tree

3 files changed

+57
-13
lines changed

3 files changed

+57
-13
lines changed
 

‎arviz/plots/kdeplot.py

+28-9
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ def plot_kde(
1515
rug=False,
1616
label=None,
1717
bw=4.5,
18+
quantiles=None,
1819
rotated=False,
1920
contour=True,
2021
fill_last=True,
@@ -44,6 +45,9 @@ def plot_kde(
4445
Bandwidth scaling factor for 1D KDE. Should be larger than 0. The higher this number the
4546
smoother the KDE will be. Defaults to 4.5 which is essentially the same as the Scott's
4647
rule of thumb (the default rule used by SciPy).
48+
quantiles : list
49+
Quantiles in ascending order used to segment the KDE. Use [.25, .5, .75] for quartiles.
50+
Defaults to None.
4751
rotated : bool
4852
Whether to rotate the 1D KDE plot 90 degrees.
4953
contour : bool
@@ -137,7 +141,6 @@ def plot_kde(
137141
if fill_kwargs is None:
138142
fill_kwargs = {}
139143

140-
fill_kwargs.setdefault("alpha", 0)
141144
fill_kwargs.setdefault("color", default_color)
142145

143146
if rug_kwargs is None:
@@ -155,6 +158,11 @@ def plot_kde(
155158
rug_space = max(density) * rug_kwargs.pop("space")
156159

157160
x = np.linspace(lower, upper, len(density))
161+
162+
if cumulative:
163+
density_q = density
164+
else:
165+
density_q = np.cumsum(density)
158166
fill_func = ax.fill_between
159167
fill_x, fill_y = x, density
160168
if rotated:
@@ -163,7 +171,6 @@ def plot_kde(
163171

164172
ax.tick_params(labelsize=xt_labelsize)
165173

166-
ax.plot(x, density, label=label, **plot_kwargs)
167174
if rotated:
168175
ax.set_xlim(0, auto=True)
169176
rug_x, rug_y = np.zeros_like(values) - rug_space, values
@@ -173,7 +180,23 @@ def plot_kde(
173180

174181
if rug:
175182
ax.plot(rug_x, rug_y, **rug_kwargs)
176-
fill_func(fill_x, fill_y, **fill_kwargs)
183+
184+
if quantiles is not None:
185+
fill_kwargs.setdefault("alpha", 0.75)
186+
187+
idx = [np.sum(density_q < quant) for quant in quantiles]
188+
189+
fill_func(
190+
fill_x,
191+
fill_y,
192+
where=np.isin(fill_x, fill_x[idx], invert=True, assume_unique=True),
193+
**fill_kwargs
194+
)
195+
else:
196+
fill_kwargs.setdefault("alpha", 0)
197+
ax.plot(x, density, label=label, **plot_kwargs)
198+
fill_func(fill_x, fill_y, **fill_kwargs)
199+
177200
if label:
178201
ax.legend()
179202
else:
@@ -233,7 +256,6 @@ def _fast_kde(x, cumulative=False, bw=4.5):
233256

234257
n_bins = min(int(len_x ** (1 / 3) * std_x * 2), 200)
235258
grid, _ = np.histogram(x, bins=n_bins)
236-
d_x = (xmax - xmin) / (n_bins - 1)
237259

238260
scotts_factor = len_x ** (-0.2)
239261
kern_nx = int(scotts_factor * 2 * np.pi * std_x)
@@ -243,13 +265,10 @@ def _fast_kde(x, cumulative=False, bw=4.5):
243265
grid = np.concatenate([grid[npad:0:-1], grid, grid[n_bins : n_bins - npad : -1]])
244266
density = convolve(grid, kernel, mode="same")[npad : npad + n_bins]
245267

246-
norm_factor = len_x * d_x * (2 * np.pi * std_x ** 2 * scotts_factor ** 2) ** 0.5
247-
248-
density = density / norm_factor
268+
density /= np.sum(density)
249269

250270
if cumulative:
251-
cs_density = np.cumsum(density)
252-
density = cs_density / cs_density[-1]
271+
density = np.cumsum(density)
253272

254273
return density, xmin, xmax
255274

‎arviz/tests/test_plots.py

+16-4
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,12 @@ def discrete_model():
9797
return {"x": np.random.randint(10, size=100), "y": np.random.randint(10, size=100)}
9898

9999

100+
@pytest.fixture(scope="module")
101+
def continuous_model():
102+
"""Simple fixture for random continuous model"""
103+
return {"x": np.random.beta(2, 5, size=100), "y": np.random.beta(2, 5, size=100)}
104+
105+
100106
@pytest.fixture(scope="function")
101107
def fig_ax():
102108
fig, ax = plt.subplots(1, 1)
@@ -228,16 +234,22 @@ def test_plot_joint_discrete(discrete_model):
228234
{"contour": False},
229235
],
230236
)
231-
def test_plot_kde(discrete_model, kwargs):
232-
axes = plot_kde(discrete_model["x"], discrete_model["y"], **kwargs)
237+
def test_plot_kde(continuous_model, kwargs):
238+
axes = plot_kde(continuous_model["x"], continuous_model["y"], **kwargs)
239+
assert axes
240+
241+
242+
@pytest.mark.parametrize("kwargs", [{"cumulative": True}, {"rug": True}])
243+
def test_plot_kde_cumulative(continuous_model, kwargs):
244+
axes = plot_kde(continuous_model["x"], quantiles=[0.25, 0.5, 0.75], **kwargs)
233245
assert axes
234246

235247

236248
@pytest.mark.parametrize(
237249
"kwargs", [{"plot_kwargs": {"linestyle": "-"}}, {"cumulative": True}, {"rug": True}]
238250
)
239-
def test_plot_kde_cumulative(discrete_model, kwargs):
240-
axes = plot_kde(discrete_model["x"], **kwargs)
251+
def test_plot_kde_quantiles(continuous_model, kwargs):
252+
axes = plot_kde(continuous_model["x"], **kwargs)
241253
assert axes
242254

243255

‎examples/plot_kde_quantiles.py

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"""
2+
KDE quantiles
3+
=============
4+
5+
_thumb: .2, .8
6+
"""
7+
import arviz as az
8+
import numpy as np
9+
10+
az.style.use("arviz-darkgrid")
11+
12+
dist = np.random.beta(np.random.uniform(0.5, 10), 5, size=1000)
13+
az.plot_kde(dist, quantiles=[0.25, 0.5, 0.75])

0 commit comments

Comments
 (0)
Please sign in to comment.