<?xml version="1.0"?>

<!--
   Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
  -->

<document xmlns="http://maven.apache.org/XDOC/2.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 https://maven.apache.org/xsd/xdoc-2.0.xsd">
  <properties>
    <title>Apache Commons Statistics User Guide</title>
  </properties>

  <body>

    <section name="" id="page_title">
      <h1>Apache Commons Statistics User Guide</h1>
    </section>

    <section name="Contents" id="toc">
      <ul>
        <li>
          <a href="#overview">Overview</a>
        </li>
        <li>
          <a href="#example-modules">Example Modules</a>
        </li>
        <li>
          <a href="#descriptive">Descriptive Statistics</a>
          <ul>
            <li>
              <a href="#desc_overview">Overview</a>
            </li>
            <li>
              <a href="#desc_examples">Examples</a>
            </li>
          </ul>
        </li>
        <li>
          <a href="#distributions">Probability Distributions</a>
          <ul>
            <li>
              <a href="#dist_overview">Overview</a>
            </li>
            <li>
              <a href="#dist_api">API</a>
            </li>
            <li>
              <a href="#dist_imp_details">Implementation Details</a>
            </li>
            <li>
              <a href="#dist_complements">Complementary Probabilities</a>
            </li>
          </ul>
        </li>
        <li>
          <a href="#inference">Inference</a>
          <ul>
            <li>
              <a href="#inference_overview">Overview</a>
            </li>
            <li>
              <a href="#inference_examples">Examples</a>
            </li>
          </ul>
        </li>
        <li>
          <a href="#interval">Interval</a>
        </li>
        <li>
          <a href="#ranking">Ranking</a>
        </li>
      </ul>
    </section>

    <section name="Overview" id="overview">
      <p>
        Apache Commons Statistics provides utilities for statistical applications. The code
        originated in the <code><a href="https://commons.apache.org/proper/commons-math/">
        commons-math</a></code> project but was pulled out into a separate project for better
        maintainability and has since undergone numerous improvements.
      </p>

      <p>
        Commons Statistics is divided into a number of submodules:
      </p>
      <ul>
        <li>
          <code><a href="../commons-statistics-descriptive/index.html">
          commons-statistics-descriptive</a></code> - Provides computation
          of descriptive statistics (mean, variance, median, etc).
        </li>
        <li>
          <code><a href="../commons-statistics-distribution/index.html">
          commons-statistics-distribution</a></code> - Provides interfaces
          and classes for probability distributions.
        </li>
        <li>
          <code><a href="../commons-statistics-inference/index.html">
          commons-statistics-inference</a></code> - Provides hypothesis testing.
        </li>
        <li>
          <code><a href="../commons-statistics-interval/index.html">
          commons-statistics-interval</a></code> - Provides statistical intervals.
        </li>
        <li>
          <code><a href="../commons-statistics-ranking/index.html">
          commons-statistics-ranking</a></code> - Provides rank transformations.
        </li>
      </ul>
    </section>

    <section name="Example Modules" id="example-modules">
      <p>
        In addition to the modules above, the Commons Statistics
        <a href="https://commons.apache.org/statistics/download_statistics.cgi">source distribution</a>
        contains example code demonstrating library functionality and/or providing useful
        development utilities. These modules are not part of the public API of the library and no
        guarantees are made concerning backwards compatibility. The
        <a href="../commons-statistics-examples/modules.html">example module parent page</a>
        contains a listing of available modules.
      </p>
      <hr/>
    </section>

    <section name="Descriptive Statistics" id="descriptive">
      <p>
        The <code>commons-statistics-descriptive</code> module provides descriptive statistics.
      </p>
      <subsection name="Overview" id="desc_overview">
        <p>
          The module provides classes to compute univariate statistics on <code>double</code>,
          <code>int</code> and <code>long</code> data using array input or a Java stream. The
          result is returned as a
          <a href="../commons-statistics-descriptive/apidocs/org/apache/commons/statistics/descriptive/StatisticResult.html">StatisticResult</a>.
          The <code>StatisticResult</code> provides methods to supply the result as a
          <code>double</code>, <code>int</code>, <code>long</code> and <code>BigInteger</code>.
          The integer types allow the exact result to be returned for integer data. For example
          the sum of <code>long</code> values may not be exactly representable as a
          <code>double</code> and may overflow a <code>long</code>.
        </p>
        <p>
          Computation of an individual statistic involves creating an instance of
          <code>StatisticResult</code> that can supply the current statistic value.
          To allow addition of single values to update the statistic, instances
          implement the primitive consumer interface for the supported type:
          <code>DoubleConsumer</code>, <code>IntConsumer</code>, or <code>LongConsumer</code>.
          Instances implement the
          <a href="../commons-statistics-descriptive/apidocs/org/apache/commons/statistics/descriptive/StatisticAccumulator.html">StatisticAccumulator</a>
          interface and can be combined with other instances. This allows computation in parallel on
          subsets of data and combination to a final result. This can be performed using the
          Java stream API.
        </p>
        <p>
          Computation of multiple statistics uses a
          <a href="../commons-statistics-descriptive/apidocs/org/apache/commons/statistics/descriptive/Statistic.html">Statistic</a>
          enumeration to define the statistics to evaluate. A container class is created to
          compute the desired statistics together and allows multiple statistics to be computed
          concurrently using the Java stream API. Each statistic result is obtained using the
          <code>Statistic</code> enum to access the required value. Providing a choice of the
          statistics allows the user to avoid the computational cost of results that are not
          required.
        </p>
        <p>
          Note that <code>double</code> computations are subject to accumulated floating-point
          rounding which can generate different results from permuted input data. Computation
          on an array of <code>double</code> data can use a multiple-pass algorithm to increase
          accuracy over a single-pass stream of values. This is the recommended approach if
          all data is already stored in an array (i.e. is not dynamically generated).
        </p>
        <p>
          If the data is an integer type then it is
          preferred to use the integer specializations of the statistics.
          Many implementations use exact integer math for the computation. This is faster than
          using a <code>double</code> data type, more accurate and returns the same result
          irrespective of the input order of the data. Note that for improved performance there
          is no use of <code>BigInteger</code> in the accumulation of intermediate values; the
          computation uses mutable fixed-precision integer classes for totals that may
          overflow 64-bits.
        </p>
        <p>
          Some statistics cannot be computed using a stream since they require all values for
          computation, for example the median. These are evaluated on an array using an instance
          of a computing class. The instance allows computation options to be changed. Instances
          are immutable and the computation is thread-safe.
        </p>
      </subsection>
      <subsection name="Examples" id="desc_examples">
        <p>
          Computation of a single statistic from an array of values, an array range or a
          stream of data:
        </p>
<source class="prettyprint">
int[] values = {1, 1, 2, 3, 5, 8, 13, 21};

double v = IntVariance.of(values).getAsDouble();

// Range uses inclusive start and exclusive end
int max = IntMax.ofRange(values, 3, 6).getAsInt();   // 8

double m = Stream.of("one", "two", "three", "four")
                 .mapToInt(String::length)
                 .collect(IntMean::create, IntMean::accept, IntMean::combine)
                 .getAsDouble();
</source>
        <p>
          Computation of multiple statistics uses the <code>Statistic</code> enum.
          These can be specified using an <code>EnumSet</code> together with the input array data.
          Note that some statistics share the same underlying computation, for example the variance,
          standard deviation and mean. When a container class is constructed using one of the
          statistics, the other co-computed statistics are available in the result even if not
          specified during construction. The <code>isSupported</code> method can
          identify all results that are available from the container class.
        </p>
<source class="prettyprint">
double[] data = {1, 2, 3, 4, 5, 6, 7, 8};
DoubleStatistics stats = DoubleStatistics.of(
    EnumSet.of(Statistic.MIN, Statistic.MAX, Statistic.VARIANCE),
    data);

stats.getAsDouble(Statistic.MIN);        // 1.0
stats.getAsDouble(Statistic.MAX);        // 8.0
stats.getAsDouble(Statistic.VARIANCE);   // 6.0

// Get other statistics supported by the underlying computations
stats.isSupported(Statistic.STANDARD_DEVIATION));   // true
stats.getAsDouble(Statistic.STANDARD_DEVIATION);    // 2.449...
</source>
        <p>
          Computation of multiple statistics on individual values can accumulate the results
          using the <code>accept</code> method of the container class:
        </p>
<source class="prettyprint">
IntStatistics stats = IntStatistics.of(
    Statistic.MIN, Statistic.MAX, Statistic.MEAN);
Stream.of("one", "two", "three", "four")
    .mapToInt(String::length)
    .forEach(stats::accept);

stats.getAsInt(Statistic.MIN);       // 3
stats.getAsInt(Statistic.MAX);       // 5
stats.getAsDouble(Statistic.MEAN);   // 15.0 / 4
</source>
        <p>
          Computation of multiple statistics on a stream of values in parallel.
          This requires use of a <code>Builder</code> that
          can supply instances of the container class to each worker with the
          <code>build</code> method. These are populated using <code>accept</code> and then
          collected using <code>combine</code>:
        </p>
<source class="prettyprint">
IntStatistics.Builder builder = IntStatistics.builder(
    Statistic.MIN, Statistic.MAX, Statistic.MEAN);
IntStatistics stats =
    Stream.of("one", "two", "three", "four")
    .parallel()
    .mapToInt(String::length)
    .collect(builder::build, IntConsumer::accept, IntStatistics::combine);

stats.getAsInt(Statistic.MIN);       // 3
stats.getAsInt(Statistic.MAX);       // 5
stats.getAsDouble(Statistic.MEAN);   // 15.0 / 4
</source>
        <p>
          Computation on multiple arrays. This requires use of a <code>Builder</code> that
          can supply instances of the container class to compute each array with the
          <code>build</code> method:
        </p>
<source class="prettyprint">
double[][] data = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
};
DoubleStatistics.Builder builder = DoubleStatistics.builder(
    Statistic.MIN, Statistic.MAX, Statistic.VARIANCE);
DoubleStatistics stats = Arrays.stream(data)
    .map(builder::build)
    .reduce(DoubleStatistics::combine)
    .get();

stats.getAsDouble(Statistic.MIN);        // 1.0
stats.getAsDouble(Statistic.MAX);        // 8.0
stats.getAsDouble(Statistic.VARIANCE);   // 6.0

// Get other statistics supported by the underlying computations
stats.isSupported(Statistic.MEAN));   // true
stats.getAsDouble(Statistic.MEAN);    // 4.5
</source>
        <p>
          If computation on multiple arrays is to be repeated then this can be done with a
          re-useable <code>java.util.stream.Collector</code>:
        </p>
<source class="prettyprint">
double[][] data = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
};
DoubleStatistics.Builder builder = DoubleStatistics.builder(
    Statistic.MIN, Statistic.MAX, Statistic.VARIANCE);
Collector&lt;double[], DoubleStatistics, DoubleStatistics&gt; collector =
    Collector.of(builder::build, (s, d) -> s.combine(builder.build(d)), DoubleStatistics::combine);
DoubleStatistics stats = Arrays.stream(data).collect(collector);

stats.getAsDouble(Statistic.MIN);        // 1.0
stats.getAsDouble(Statistic.MAX);        // 8.0
stats.getAsDouble(Statistic.VARIANCE);   // 6.0
</source>
        <p>
          Combination of multiple statistics requires them to be compatible, i.e. all supported
          statistics in one container are also supported in the other. Note that combining another
          container ignores any unsupported statistics and the compatibility
          may be asymmetric.
        </p>
<source class="prettyprint">
double[] data1 = {1, 2, 3, 4};
double[] data2 = {5, 6, 7, 8};
DoubleStatistics varStats = DoubleStatistics.builder(Statistic.VARIANCE).build(data1);
DoubleStatistics meanStats = DoubleStatistics.builder(Statistic.MEAN).build(data2);

// throws IllegalArgumentException
varStats.combine(meanStats);

// OK - mean is updated to 4.5
meanStats.combine(varStats)
</source>
      <p>
        Computation of a statistic that requires all data (i.e. does not support the
        <code>Stream</code> API) uses a configurable instance of the computing class:
      </p>
<source class="prettyprint">
double[] data = {8, 7, 6, 5, 4, 3, 2, 1};
// Configure the statistic
double m = Median.withDefaults()
                 .withCopy(true)          // do not modify the input array
                 .with(NaNPolicy.ERROR)   // raise an exception for NaN
                 .evaluate(data);
// m = 4.5
</source>
      <p>
        Computation of multiple values of a statistic that requires all data:
      </p>
<source class="prettyprint">
int size = 10000;
double origin = 0;
double bound = 100;
double[] data =
    new SplittableRandom(123)
    .doubles(size, origin, bound)
    .toArray();
// Evaluate multiple statistics on the same data
double[] q = Quantile.withDefaults()
                     .evaluate(data, 0.25, 0.5, 0.75);   // probabilities
// q ~ [25.0, 50.0, 75.0]
</source>
      <p>
        Computation of quantiles requires partial sorting of array data.
        Quantile support for pre-sorted numeric data of type <code>double</code> or
        <code>long</code> uses the interfaces <code>IntToDoubleFunction</code> and
        <code>IntToLongFunction</code> to specify the value at each position in the sorted data.
        This allows computation on numeric types such as <code>short</code> or <code>float</code>
        not supported by the array computation methods.
      </p>
<source class="prettyprint">
int size = 10000;
int exclusiveBound = 101;
short[] data = new short[size];
SplittableRandom rng = new SplittableRandom(123);
for (int i = 0; i &lt; size; i++) {
    data[i] = (short) rng.nextInt(exclusiveBound);
}
// Sorted data
Arrays.sort(data);
double[] q = Quantile.withDefaults()
                     .evaluate(size, i -&gt; data[i], 0.25, 0.5, 0.75);
// q ~ [25.0, 50.0, 75.0]
</source>
      <p>
        Note it is not recommended to sort supported array types
        <b>only</b> for use in the quantile evaluation.
        However if the data must be sorted for other reasons, or is already sorted, then these
        methods can be used on supported array data to compute
        the same result without the cost of partial re-sorting of sorted data.
      </p>
      </subsection>
    </section>

    <section name="Probability Distributions" id="distributions">
      <subsection name="Overview" id="dist_overview">
        <p>
          The <code>commons-statistics-distribution</code> module provides a framework and implementations for some commonly used
          probability distributions. Continuous univariate distributions are represented by
          implementations of the
          <a href="../commons-statistics-distribution/apidocs/org/apache/commons/statistics/distribution/ContinuousDistribution.html">ContinuousDistribution</a>
          interface.  Discrete distributions implement
          <a href="../commons-statistics-distribution/apidocs/org/apache/commons/statistics/distribution/DiscreteDistribution.html">DiscreteDistribution</a>
          (values must be mapped to integers).
        </p>
      </subsection>
      <subsection name="API" id="dist_api">
        <p>
          The distribution framework provides the means to compute probability density,
          probability mass and cumulative probability functions for several well-known
          discrete (integer-valued) and continuous probability distributions.
          The API also allows for the computation of inverse cumulative probabilities
          and sampling from distributions.
        </p>
        <p>
          For an instance <code>f</code> of a distribution <code>F</code>,
          and a domain value, <code>x</code>, <code>f.cumulativeProbability(x)</code>
          computes <code>P(X &lt;= x)</code> where <code>X</code> is a random variable distributed
          as <code>F</code>. The complement of the cumulative probability,
          <code>f.survivalProbability(x)</code> computes <code>P(X &gt; x)</code>. Note that
          the survival probability is approximately equal to <code>1 - P(X &lt;= x)</code> but
          does not suffer from cancellation error as the cumulative probability approaches 1.
          The cancellation error may cause a (total) loss of accuracy when
          <code>P(X &lt;= x) ~ 1</code>
          (see <a href="#complements">complementary probabilities</a>).
        </p>
<source class="prettyprint">
TDistribution t = TDistribution.of(29);
double lowerTail = t.cumulativeProbability(-2.656);   // P(T(29) &lt;= -2.656)
double upperTail = t.survivalProbability(2.75);       // P(T(29) &gt; 2.75)
</source>
        <p>
          For <a href="../commons-statistics-distribution/apidocs/org/apache/commons/statistics/distribution/DiscreteDistribution.html">discrete</a>
          <code>F</code>, the probability mass function is given by <code>f.probability(x)</code>.
          For <a href="../commons-statistics-distribution/apidocs/org/apache/commons/statistics/distribution/ContinuousDistribution.html">continuous</a>
          <code>F</code>, the probability density function is given by <code>f.density(x)</code>.
          Distributions also implement <code>f.probability(x1, x2)</code> for computing
          <code>P(x1 &lt; X &lt;= x2)</code>.
        </p>
<source class="prettyprint">
PoissonDistribution pd = PoissonDistribution.of(1.23);
double p1 = pd.probability(5);
double p2 = pd.probability(5, 5);
double p3 = pd.probability(4, 5);
// p2 == 0
// p1 == p3
</source>
        <p>
          Inverse distribution functions can be computed using the
          <code>inverseCumulativeProbability</code> and <code>inverseSurvivalProbability</code>
          methods. For continuous <code>f</code> and <code>p</code> a probability,
          <code>f.inverseCumulativeProbability(p)</code> returns
        </p>
        <p>
          \[ x = \begin{cases}
             \inf \{ x \in \mathbb R : P(X \le x) \ge p\}   &amp; \text{for } 0 \lt p \le 1 \\
             \inf \{ x \in \mathbb R : P(X \le x) \gt 0 \}  &amp; \text{for } p = 0
             \end{cases} \]
        </p>
        <p>
          where <code>X</code> is distributed as <code>F</code>.<br/>
          Likewise <code>f.inverseSurvivalProbability(p)</code> returns
        </p>
        <p>
          \[ x = \begin{cases}
             \inf \{ x \in \mathbb R : P(X \gt x) \le p\}   &amp; \text{for } 0 \le p \lt 1 \\
             \inf \{ x \in \mathbb R : P(X \gt x) \lt 1 \}  &amp; \text{for } p = 1
             \end{cases} \]
        </p>
<source class="prettyprint">
NormalDistribution n = NormalDistribution.of(0, 1);
double x1 = n.inverseCumulativeProbability(1e-300);
double x2 = n.inverseSurvivalProbability(1e-300);
// x1 == -x2 ~ -37.0471
</source>
        <p>
          For discrete <code>F</code>, the definition is the same, with \( \mathbb Z \)
          (the integers) in place of \( \mathbb R \). Note that, in the discrete case,
          the strict inequality on \( p \) in the definition can make a difference when
          \( p \) is an attained value of the distribution. For example moving to the next
          larger value of \( p \) will return the value \( x + 1 \) for inverse CDF.
        </p>
        <p>
          All distributions provide accessors for the parameters used to create the distribution,
          and a mean and variance. The return value when the mean or variance
          is undefined is noted in the class javadoc.
        </p>
<source class="prettyprint">
ChiSquaredDistribution chi2 = ChiSquaredDistribution.of(42);
double df = chi2.getDegreesOfFreedom();    // 42
double mean = chi2.getMean();              // 42
double variance = chi2.getVariance();      // 84

CauchyDistribution cauchy = CauchyDistribution.of(1.23, 4.56);
double location = cauchy.getLocation();    // 1.23
double scale = cauchy.getScale();          // 4.56
double undefined1 = cauchy.getMean();      // NaN
double undefined2 = cauchy.getVariance();  // NaN
</source>
        <p>
          The supported domain of the distribution is provided by the
          <code>getSupportLowerBound</code> and <code>getSupportUpperBound</code> methods.
        </p>
<source class="prettyprint">
BinomialDistribution b = BinomialDistribution.of(13, 0.15);
int lower = b.getSupportLowerBound();  // 0
int upper = b.getSupportUpperBound();  // 13
</source>
        <p>
          All distributions implement a <code>createSampler(UniformRandomProvider rng)</code>
          method to support random sampling from the distribution, where <code>UniformRandomProvider</code>
          is an interface defined in <a href="https://commons.apache.org/proper/commons-rng/">Commons RNG</a>.
          The sampler is a functional interface whose functional method is <code>sample()</code>,
          suitable for generation of <code>double</code> or <code>int</code> samples.
          Default <code>samples()</code> methods are provided to create a
          <code>DoubleStream</code> or <code>IntStream</code>.
        </p>
<source class="prettyprint">
// From Commons RNG Simple
UniformRandomProvider rng = RandomSource.KISS.create(123L);

NormalDistribution n = NormalDistribution.of(0, 1);
double x = n.createSampler(rng).sample();

// Generate a number of samples
GeometricDistribution g = GeometricDistribution.of(0.75);
int[] k = g.createSampler(rng).samples(100).toArray();
// k.length == 100
</source>
        <p>
          Note that even when distributions are immutable, the sampler is not immutable as it
          depends on the instance of the mutable <code>UniformRandomProvider</code>. Generation of
          many samples in a multi-threaded application should use a separate instance of
          <code>UniformRandomProvider</code> per thread. Any synchronization should be avoided
          for best performance. By default the streams returned from the <code>samples()</code>
          methods are sequential.
        </p>
      </subsection>
      <subsection name="Implementation Details" id="dist_imp_details">
        <p>
          Instances are constructed using factory methods, typically a static method in the
          distribution class named <code>of</code>. This allows the returned instance
          to be specialised to the distribution parameters.
        </p>
        <p>
          Exceptions will be raised by the factory method when constructing the distribution
          using invalid parameters. See the class javadoc for exception conditions.
        </p>
        <p>
          Unless otherwise noted, distribution instances are immutable. This allows sharing
          an instance between threads for computations.
        </p>
        <p>
          Exceptions will not be raised by distributions for an invalid <code>x</code> argument
          to probability functions. Typically the cumulative probability functions will return
          0 or 1 for an out-of-domain argument, depending on which the side of the domain bound
          the argument falls, and the density or probability mass functions return 0.
          Return values for <code>x</code> arguments when the result is
          undefined should be documented in the class javadoc. For example the beta distribution
          is undefined for <code>x = 0, alpha &lt; 1</code> or <code>x = 1, beta &lt; 1</code>.
          Note: This out-of-domain behaviour may be different from distributions in the
          <code>org.apache.commons.math3.distribution</code> package. Users upgrading from
          <code><a href="https://commons.apache.org/proper/commons-math/">commons-math</a></code>
          should check the appropriate class javadoc.
        </p>
        <p>
          An exception will be raised by distributions for an invalid <code>p</code> argument
          to inverse probability functions. The argument must be in the range <code>[0, 1]</code>.
        </p>
      </subsection>
      <subsection name="Complementary Probabilities" id="dist_complements">
        <p>
          The distributions provide the cumulative probability <code>p</code> and its complement,
          the survival probability, <code>q = 1 - p</code>. When the probability
          <code>q</code> is small use of the cumulative probability to compute <code>q</code> can
          result in dramatic loss of accuracy. This is due to the distribution of floating-point
          numbers having a
          <a href="https://en.wikipedia.org/wiki/Reciprocal_distribution">log-uniform</a>
          distribution as the limiting distribution. There are far more
          representable numbers as the probability value approaches zero than when it approaches
          one.
        </p>
        <p>
          The difference is illustrated with the result of computing the upper tail of a
          probability distribution.
        </p>
<source class="prettyprint">
ChiSquaredDistribution chi2 = ChiSquaredDistribution.of(42);
double q1 = 1 - chi2.cumulativeProbability(168);
double q2 = chi2.survivalProbability(168);
// q1 == 0
// q2 != 0
</source>
        <p>
          In this case the value <code>1 - p</code> has only a single bit of information as
          <code>x</code> approaches 168. For example the value <code>1 - p(x=167)</code>
          is <code>2<sup>-53</sup></code> (or approximately <code>1.11e-16</code>).
          The complement <code>q</code> retains information
          much further into the long tail as shown in the following table:
        </p>
        <table border="1" style="width: auto">
          <tr><th colspan="3">Chi-squared distribution, 42 degrees of freedom</th></tr>
          <tr><th>x</th><th>1 - p</th><th>q</th></tr>
          <tr><td>166</td><td>1.11e-16</td><td>1.16e-16</td></tr>
          <tr><td>167</td><td>1.11e-16</td><td>7.96e-17</td></tr>
          <tr><td>168</td><td>0</td><td>5.43e-17</td></tr>
          <tr><td>...</td><td></td><td></td></tr>
          <tr><td>200</td><td>0</td><td>1.19e-22</td></tr>
        </table>
        <p>
          Probability computations should use the appropriate cumulative or survival function
          to calculate the lower or upper tail respectively. The same care should be applied
          when inverting probability distributions. It is preferred to compute either
          <code>p &le; 0.5</code> or <code>q &le; 0.5</code> without loss of accuracy and then
          invert respectively the cumulative probability using <code>p</code> or the survival
          probabilty using <code>q</code> to obtain <code>x</code>.
        </p>
<source class="prettyprint">
ChiSquaredDistribution chi2 = ChiSquaredDistribution.of(42);
double q = 5.43e-17;
// Incorrect: p = 1 - q == 1.0 !!!
double x1 = chi2.inverseCumulativeProbability(1 - q);
// Correct: invert q
double x2 = chi2.inverseSurvivalProbability(q);
// x1 == +infinity
// x2 ~ 168.0
</source>
        <p>
          Note: The survival probability functions were not present in the
          <code>org.apache.commons.math3.distribution</code> package. Users upgrading from
          <code><a href="https://commons.apache.org/proper/commons-math/">commons-math</a></code>
          should update usage of the cumulative probability functions where appropriate.
        </p>
      </subsection>
    </section>

    <section name="Inference" id="inference">
      <p>
        The <code>commons-statistics-inference</code> module provides hypothesis testing.
      </p>
      <subsection name="Overview" id="inference_overview">
        <p>
          The module provides test classes that implement a single, or family, of statistical
          tests. Each test class provides methods to compute a test statistic and a p-value for the
          significance of the statistic. These can be computed together using a <code>test</code>
          method and returned as a
          <a href="../commons-statistics-inference/apidocs/org/apache/commons/statistics/inference/DiscreteDistribution.html">SignificanceResult</a>.
          The <code>SignificanceResult</code> has a method that can be used to <code>reject</code>
          the null hypothesis at the provided significance level. Test classes may extend the
          <code>SignificanceResult</code> to return more information about the test result,
          for example the computed degrees of freedom.
        </p>
        <p>
          Alternatively a <code>statistic</code> method is provided to compute <i>only</i> the
          statistic as a <code>double</code> value. This statistic can be compared to a pre-computed
          critical value, for example from a table of critical values.
        </p>
        <p>
          A test is obtained using the <code>withDefaults()</code> method to return the test with
          all options set to their default value. Any test options can be configured using
          property change methods to return a new instance of the test. Tests that support an
          <a href="../commons-statistics-inference/apidocs/org/apache/commons/statistics/inference/AlternativeHypothesis.html">
          alternate hypothesis</a> will use a two-sided test by default. Test that support multiple
          <a href="../commons-statistics-inference/apidocs/org/apache/commons/statistics/inference/PValueMethod.html">
          p-value methods</a> will default to an appropriate computation for the size of the input
          data. Unless otherwise noted test instances are immutable.
        </p>
      </subsection>
      <subsection name="Examples" id="inference_examples">
        <p>
          A chi-square test that the observed counts conform to the expected frequencies.
        </p>
<source class="prettyprint">
double[] expected = {0.25, 0.5, 0.25};
long[] observed = {57, 123, 38};

SignificanceResult result = ChiSquareTest.withDefaults()
                                         .test(expected, observed);
result.getPValue();    // 0.0316148
result.reject(0.05);   // true
result.reject(0.01);   // false
</source>
        <p>
          A paired t-test that the marks in the math exam were greater than the science
          exam. This fails to reject the null hypothesis (that there was no difference) with
          95% confidence.
        </p>
<source class="prettyprint">
double[] math    = {53, 69, 65, 65, 67, 79, 86, 65, 62, 69};   // mean = 68.0
double[] science = {75, 65, 68, 63, 55, 65, 73, 45, 51, 52};   // mean = 61.2

SignificanceResult result = TTest.withDefaults()
                                 .with(AlternativeHypothesis.GREATER_THAN)
                                 .pairedTest(math, science);
result.getPValue();    // 0.05764
result.reject(0.05);   // false
</source>
        <p>
          A G-test that the allele frequencies conform to the expected Hardy-Weinberg proportions.
          This is an example of an intrinsic hypothesis where the expected frequencies are computed
          using the observations and the degrees of freedom must be adjusted.
          The data is from McDonald (1989) Selection component analysis
          of the Mpi locus in the amphipod Platorchestia platensis.
          <i>Heredity</i> <b>62</b>: 243-249.
        </p>
<source class="prettyprint">
// Allele frequencies: Mpi 90/90, Mpi 90/100, Mpi 100/100
long[] observed = {1203, 2919, 1678};
// Mpi 90 proportion
double p = (2.0 * observed[0] + observed[1]) /
           (2 * Arrays.stream(observed).sum());   // 5325 / 11600 = 0.459

// Hardy-Weinberg proportions
double[] expected = {p * p, 2 * p * (1 - p), (1 - p) * (1 - p)};
// 0.211, 0.497, 0.293

SignificanceResult result = GTest.withDefaults()
                                 .withDegreesOfFreedomAdjustment(1)
                                 .test(expected, observed);
result.getStatistic();   // 1.03
result.getPValue();      // 0.309
result.reject(0.05);     // false
</source>
        <p>
          A one-way analysis of variance test. This is an example where the result has more
          information than the test statistic and the p-value.
          The data is from McDonald <i>et al</i> (1991) Allozymes and morphometric characters of
          three species of Mytilus in the Northern and Southern Hemispheres.
          <i>Marine Biology</i> <b>111</b>: 323-333.
        </p>
<source class="prettyprint">
double[] tillamook = {0.0571, 0.0813, 0.0831, 0.0976, 0.0817, 0.0859, 0.0735, 0.0659, 0.0923, 0.0836};
double[] newport = {0.0873, 0.0662, 0.0672, 0.0819, 0.0749, 0.0649, 0.0835, 0.0725};
double[] petersburg = {0.0974, 0.1352, 0.0817, 0.1016, 0.0968, 0.1064, 0.105};
double[] magadan = {0.1033, 0.0915, 0.0781, 0.0685, 0.0677, 0.0697, 0.0764, 0.0689};
double[] tvarminne = {0.0703, 0.1026, 0.0956, 0.0973, 0.1039, 0.1045};

Collection&lt;double[]&gt; data = Arrays.asList(tillamook, newport, petersburg, magadan, tvarminne);
OneWayAnova.Result result = OneWayAnova.withDefaults()
                                       .test(data);
result.getStatistic();   // 7.12
result.getPValue();      // 2.8e-4
result.reject(0.001);    // true
</source>
      <p>
        The result also provides the between and within group degrees of freedom and the mean
        squares allowing reporting of the results in a table:
      </p>
      <table>
        <tr><th></th><th>degrees of freedom</th><th>mean square</th><th>F</th><th>p</th></tr>
        <tr><td>between groups</td><td>4</td><td>0.001113</td><td>7.12</td><td>2.8e-4</td></tr>
        <tr><td>within groups</td><td>34</td><td>0.000159</td><td></td><td></td></tr>
      </table>
      </subsection>
    </section>
    <section name="Interval" id="interval">
      <p>
        The <code>commons-statistics-interval</code> module provides statistical intervals.
      </p>
      <p>
        The <code>Interval</code> interface provides a bounded interval with a lower and upper
        bound: \( [l, u] \).
      </p>
      <p>
        The <code>BinomialConfidenceInterval</code> enumeration provides methods
        to create a confidence interval for a binomial proportion. This is an interval
        containing the probability of success given a series of success-failure experiments.
        The interval is constructed using a confidence level. For example a 95% confidence interval
        will contain the true proportion of successes 95% of the times that the procedure
        for constructing the confidence interval is employed. The target error rate \( \alpha \)
        is defined as \( 1 - confidence \) when expressing the confidence level as a probability
        in \( (0, 1) \).
      </p>
      <p>
        The following example demonstrates an ideal coin toss experiment. Note how the 95%
        confidence interval containing the true probability narrows as the number of trials
        increases.
      </p>
<source class="prettyprint">
BinomialConfidenceInterval method = BinomialConfidenceInterval.WILSON_SCORE;
double alpha = 0.05;

Interval interval = method.fromErrorRate(10, 5, alpha);
interval.getLowerBound();   // 0.23659
interval.getUpperBound();   // 0.76341

method.fromErrorRate(100, 50, alpha);       // 0.40383, 0.59617
method.fromErrorRate(1000, 500, alpha);     // 0.46907, 0.53093
method.fromErrorRate(10000, 5000, alpha);   // 0.49020, 0.50980
</source>
      <p>
        The <code>NormalConfidenceInterval</code> enumeration provides methods
        to create a confidence interval for a normally distributed population.
        Intervals can be created for the mean or the variance from a sample of
        the population.
      </p>
      <p>
        The following example demonstrates how to generate a 95% confidence interval
        for the mean given a sample. The mean and variance of the sample are
        required for the interval; here they are generated using the descriptive
        statistics API.
      </p>
<source class="prettyprint">
double[] x = {
    1.47, 1.40, 1.55, 1.44, 1.41,
    1.38, 1.53, 1.42, 1.55, 1.55,
    1.31, 1.37, 1.53, 1.47, 1.51
};
DoubleStatistics stats = DoubleStatistics.of(EnumSet.of(Statistic.MEAN, Statistic.VARIANCE), x);

double mean = stats.getAsDouble(Statistic.MEAN);          // 1.46
double variance = stats.getAsDouble(Statistic.VARIANCE);  // 0.0058
long n = stats.getCount();                                // 15
double alpha = 0.05;

Interval interval = NormalConfidenceInterval.MEAN.fromErrorRate(mean, variance, n, alpha);
interval.getLowerBound();   // 1.4170
interval.getUpperBound();   // 1.5017
</source>
    </section>
    <section name="Ranking" id="ranking">
      <p>
        The <code>commons-statistics-ranking</code> module provides rank transformations.
      </p>
      <p>
        The <code>NaturalRanking</code> class provides a ranking based on the natural ordering
        of floating-point values. Ranks are assigned to the input numbers in ascending order,
        starting from 1.
      </p>
<source class="prettyprint">
NaturalRanking ranking = new NaturalRanking();
ranking.apply(new double[] {5, 6, 7, 8});   // 1, 2, 3, 4
ranking.apply(new double[] {8, 5, 7, 6});   // 4, 1, 3, 2
</source>
      <p>
        The special case of <code>NaN</code> values are handled using the configured
        <code>NaNStragegy</code>. The default is to raise an exception.
      </p>
<source class="prettyprint">
double[] data = new double[] {6, 5, Double.NaN, 7};
new NaturalRanking().apply(data);                      // IllegalArgumentException
new NaturalRanking(NaNStrategy.MINIMAL).apply(data);   // (4, 2, 1, 3)
new NaturalRanking(NaNStrategy.MAXIMAL).apply(data);   // (3, 1, 4, 2)
new NaturalRanking(NaNStrategy.REMOVED).apply(data);   // (3, 1, 2)
new NaturalRanking(NaNStrategy.FIXED).apply(data);     // (3, 1, NaN, 2)
new NaturalRanking(NaNStrategy.FAILED).apply(data);    // IllegalArgumentException
</source>
      <p>
        Ties are handled using the configured <code>TiesStragegy</code>. The default is to
        use an average.
      </p>
<source class="prettyprint">
double[] data = new double[] {7, 5, 7, 6};
new NaturalRanking().apply(data);                          // (3.5, 1, 3.5, 2)
new NaturalRanking(TiesStrategy.SEQUENTIAL).apply(data);   // (3, 1, 4, 2)
new NaturalRanking(TiesStrategy.MINIMUM).apply(data);      // (3, 1, 3, 2)
new NaturalRanking(TiesStrategy.MAXIMUM).apply(data);      // (4, 1, 4, 2)
new NaturalRanking(TiesStrategy.AVERAGE).apply(data);      // (3.5, 1, 3.5, 2)
new NaturalRanking(TiesStrategy.RANDOM).apply(data);       // (3, 1, 4, 2)  or  (4, 1, 3, 2)
</source>
      <p>
        The source of randomness defaults to a system supplied generator. The randomness can be
        provided as a <code>LongSupplier</code> of random 64-bit values.
      </p>
<source class="prettyprint">
double[] data = new double[] {7, 5, 7, 6};
new NaturalRanking(TiesStrategy.RANDOM).apply(data);
new NaturalRanking(new SplittableRandom()::nextInt).apply(data);
// From Commons RNG
UniformRandomProvider rng = RandomSource.KISS.create();
new NaturalRanking(rng::nextInt).apply(data);
// ranks: (3, 1, 4, 2)  or  (4, 1, 3, 2)
</source>
    </section>

  </body>

</document>
