![]() |
Home | Libraries | People | FAQ | More |
If a statistical distribution is discrete then the random
variable can only have integer values - this leaves us with a problem when
calculating quantiles - we can either ignore the discreteness of the distribution
and return a real value, or we can round to an integer. As it happens, computing
integer values can be substantially faster than calculating a real value,
so there are definite advantages to returning an integer, but we do then
need to decide how best to round the result. The discrete_quantile
policy defines how discrete quantiles work, and how integer results are rounded:
enum discrete_quantile_policy_type { real, integer_round_outwards, integer_round_inwards, integer_round_down, integer_round_up, // default integer_round_nearest }; template <discrete_quantile_policy_type> struct discrete_quantile;
The values that discrete_quantile
can take have the following meanings:
Ignores the discreteness of the distribution, and returns a real-valued result. For example:
#include <boost/math/distributions/negative_binomial.hpp> using boost::math::negative_binomial_distribution; using namespace boost::math::policies; typedef negative_binomial_distribution< double, policy<discrete_quantile<real> > > dist_type; // Lower 5% quantile: double x = quantile(dist_type(20, 0.3), 0.05); // Upper 95% quantile: double y = quantile(complement(dist_type(20, 0.3), 0.05));
Results in x =
27.3898 and y
= 68.1584.
An integer value is returned so that:
This is normally the safest rounding policy, since it ensures that both one and two sided intervals are guaranteed to have at least the requested coverage. For example:
#include <boost/math/distributions/negative_binomial.hpp> using boost::math::negative_binomial_distribution; using namespace boost::math::policies; typedef negative_binomial_distribution< double, policy<discrete_quantile<integer_round_outwards> > > dist_type; // Lower quantile rounded down: double x = quantile(dist_type(20, 0.3), 0.05); // 27 rounded down from 27.3898 // Upper quantile rounded up: double y = quantile(complement(dist_type(20, 0.3), 0.05)); // 69 rounded up from 68.1584
Results in x =
27 (rounded down from 27.3898) and
y =
69 (rounded up from 68.1584).
The variables x and y are now defined so that:
cdf(negative_binomial(20), x) <= 0.05 cdf(negative_binomial(20), y) >= 0.95
In other words we guarantee at least 90% coverage in the central region overall, and also no more than 5% coverage in each tail.
This is the opposite of integer_round_outwards: an integer value is returned so that:
For example:
#include <boost/math/distributions/negative_binomial.hpp> using boost::math::negative_binomial_distribution; using namespace boost::math::policies; typedef negative_binomial_distribution< double, policy<discrete_quantile<integer_round_inwards> > > dist_type; // Lower quantile rounded up: double x = quantile(dist_type(20, 0.3), 0.05); // 28 rounded up from 27.3898 // Upper quantile rounded down: double y = quantile(complement(dist_type(20, 0.3), 0.05)); // 68 rounded down from 68.1584
Results in x =
28 (rounded up from 27.3898) and y = 68
(rounded down from 68.1584).
The variables x and y are now defined so that:
cdf(negative_binomial(20), x) >= 0.05 cdf(negative_binomial(20), y) <= 0.95
In other words we guarantee at no more than 90% coverage in the central region overall, and also at least 5% coverage in each tail.
Always rounds down to an integer value, no matter whether it's an upper or
a lower quantile: quantile(dist,
p)
is the largest integer k with cdf(dist,
k) <= p,
and quantile(complement(dist, q)) the
largest k with cdf(complement(dist,
k)) >= q.
This is the default policy. It always rounds up to an integer value, no matter
whether it's an upper or a lower quantile: quantile(dist,
p)
is the smallest integer k with cdf(dist,
k) >= p,
and quantile(complement(dist, q)) the
smallest k with cdf(complement(dist,
k)) <= q.
This is the usual definition of the quantile of a discrete distribution,
and the one R, SciPy, Julia and Mathematica use. For example the 5% and 95%
quantiles of binomial(50, 0.5) are 19 and 31: cdf(binomial(50,
0.5), 18) <
0.05 <=
cdf(binomial(50, 0.5), 19)
and cdf(binomial(50, 0.5), 30)
< 0.95
<= cdf(binomial(50,
0.5), 31).
All of the discrete distributions (binomial, negative binomial, Poisson,
geometric, hypergeometric and Bernoulli) settle the answer on the cdf at
integers, so quantile(dist, cdf(dist, k))
== k
and quantile(complement(dist, cdf(complement(dist,
k))))
== k,
except where the cdf rounds to the same value at consecutive integers (then
the smallest of them is returned), and except that p
== 1
(or q ==
0) gives the end of the support for
distributions that have one, since only there is the cdf exactly 1.
Always rounds to the nearest integer value, no matter whether it's an upper or a lower quantile. This will produce the requested coverage in the average case, but for any specific example may results in either significantly more or less coverage than the requested amount. For example:
For example:
#include <boost/math/distributions/negative_binomial.hpp> using boost::math::negative_binomial_distribution; using namespace boost::math::policies; typedef negative_binomial_distribution< double, policy<discrete_quantile<integer_round_nearest> > > dist_type; // Lower quantile rounded (down) to nearest: double x = quantile(dist_type(20, 0.3), 0.05); // 27 // Upper quantile rounded (down) to nearest: double y = quantile(complement(dist_type(20, 0.3), 0.05)); // 68
Results in x =
27 (rounded from 27.3898) and y = 68
(rounded from 68.1584).