This is an automated email from the ASF dual-hosted git repository.
erans pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-math.git
The following commit(s) were added to refs/heads/master by this push:
new 0df313b MATH-1401: Cover all possible inputs.
0df313b is described below
commit 0df313bef62d5fedc18286b80fc93248b5f180fd
Author: Gilles Sadowski <[email protected]>
AuthorDate: Thu Apr 18 14:43:27 2019 +0200
MATH-1401: Cover all possible inputs.
Thanks to Michele De Stefano.
---
src/changes/changes.xml | 4 +-
.../stat/interval/ClopperPearsonInterval.java | 22 ++++----
.../stat/interval/ClopperPearsonIntervalTest.java | 64 ++++++++++++++++++++++
3 files changed, 76 insertions(+), 14 deletions(-)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 8b5f8e5..090969c 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -54,8 +54,8 @@ If the output is not quite correct, check for invisible
trailing spaces!
</release>
<release version="4.0" date="XXXX-XX-XX" description="">
- <action dev="erans" type="fix" issue="MATH-1401">
- "ClopperPearsonInterval": Fixed case where number of trials equals
number of successes.
+ <action dev="erans" type="fix" issue="MATH-1401" due-to="Michele De
Stefano">
+ "ClopperPearsonInterval": Missing cases.
</action>
<action dev="erans" type="add" issue="MATH-1477" due-to="Chee Sing Lee">
"MillerUpdatingRegression": Fixed "ArrayIndexOutOfBounds" exception.
diff --git
a/src/main/java/org/apache/commons/math4/stat/interval/ClopperPearsonInterval.java
b/src/main/java/org/apache/commons/math4/stat/interval/ClopperPearsonInterval.java
index 5bf642c..27cdc84 100644
---
a/src/main/java/org/apache/commons/math4/stat/interval/ClopperPearsonInterval.java
+++
b/src/main/java/org/apache/commons/math4/stat/interval/ClopperPearsonInterval.java
@@ -35,26 +35,24 @@ public class ClopperPearsonInterval implements
BinomialConfidenceInterval {
double confidenceLevel) {
IntervalUtils.checkParameters(numberOfTrials, numberOfSuccesses,
confidenceLevel);
double lowerBound = 0;
- double upperBound = 0;
+ double upperBound = 1;
- if (numberOfSuccesses > 0) {
- final double alpha = 0.5 * (1 - confidenceLevel);
+ final double alpha = 0.5 * (1 - confidenceLevel);
+ if (numberOfSuccesses > 0) {
final FDistribution distributionLowerBound = new FDistribution(2 *
(numberOfTrials - numberOfSuccesses + 1),
2 *
numberOfSuccesses);
final double fValueLowerBound =
distributionLowerBound.inverseCumulativeProbability(1 - alpha);
lowerBound = numberOfSuccesses /
(numberOfSuccesses + (numberOfTrials - numberOfSuccesses + 1)
* fValueLowerBound);
+ }
- if (numberOfSuccesses != numberOfTrials) {
- final FDistribution distributionUpperBound = new
FDistribution(2 * (numberOfSuccesses + 1),
-
2 * (numberOfTrials - numberOfSuccesses));
- final double fValueUpperBound =
distributionUpperBound.inverseCumulativeProbability(1 - alpha);
- upperBound = (numberOfSuccesses + 1) * fValueUpperBound /
- (numberOfTrials - numberOfSuccesses + (numberOfSuccesses +
1) * fValueUpperBound);
- } else {
- upperBound = 1;
- }
+ if (numberOfSuccesses < numberOfTrials) {
+ final FDistribution distributionUpperBound = new FDistribution(2 *
(numberOfSuccesses + 1),
+ 2 *
(numberOfTrials - numberOfSuccesses));
+ final double fValueUpperBound =
distributionUpperBound.inverseCumulativeProbability(1 - alpha);
+ upperBound = (numberOfSuccesses + 1) * fValueUpperBound /
+ (numberOfTrials - numberOfSuccesses + (numberOfSuccesses + 1)
* fValueUpperBound);
}
return new ConfidenceInterval(lowerBound, upperBound, confidenceLevel);
diff --git
a/src/test/java/org/apache/commons/math4/stat/interval/ClopperPearsonIntervalTest.java
b/src/test/java/org/apache/commons/math4/stat/interval/ClopperPearsonIntervalTest.java
index a8a1db1..6a06f97 100644
---
a/src/test/java/org/apache/commons/math4/stat/interval/ClopperPearsonIntervalTest.java
+++
b/src/test/java/org/apache/commons/math4/stat/interval/ClopperPearsonIntervalTest.java
@@ -46,4 +46,68 @@ public class ClopperPearsonIntervalTest extends
BinomialConfidenceIntervalAbstra
Assert.assertEquals(0.025, interval.getLowerBound(), 1e-16);
Assert.assertEquals(1, interval.getUpperBound(), 0d);
}
+
+ // number of successes = 0, number of trials = N
+ @Test
+ public void testCase1() {
+ // Check correctness against values obtained with the Python
statsmodels.stats.proportion.proportion_confint
+ final int successes = 0;
+ final int trials = 10;
+ final double confidenceLevel = 0.95;
+
+ // proportion_confint(0,10,method='beta') = (0, 0.3084971078187608)
+ final ConfidenceInterval expected = new ConfidenceInterval(0,
+
0.3084971078187608,
+
confidenceLevel);
+
+ check(expected,
createBinomialConfidenceInterval().createInterval(trials, successes,
confidenceLevel));
+ }
+
+ // number of successes = number of trials = N
+ @Test
+ public void testCase2() {
+ // Check correctness against values obtained with the Python
statsmodels.stats.proportion.proportion_confint
+ final int successes = 10;
+ final int trials = 10;
+ final double confidenceLevel = 0.95;
+
+ // prop.proportion_confint(10,10,method='beta') = (0.6915028921812392,
1)
+ final ConfidenceInterval expected = new
ConfidenceInterval(0.6915028921812392,
+ 1,
+
confidenceLevel);
+
+ check(expected,
createBinomialConfidenceInterval().createInterval(trials, successes,
confidenceLevel));
+ }
+
+ // number of successes = k, number of trials = N, 0 < k < N
+ @Test
+ public void testCase3() {
+ // Check correctness against values obtained with the Python
statsmodels.stats.proportion.proportion_confint
+ final int successes = 3;
+ final int trials = 10;
+ final double confidenceLevel = 0.95;
+
+ // prop.proportion_confint(3,10,method='beta') = (0.06673951117773447,
0.6524528500599972)
+ final ConfidenceInterval expected = new
ConfidenceInterval(0.06673951117773447,
+
0.6524528500599972,
+
confidenceLevel);
+
+ check(expected,
createBinomialConfidenceInterval().createInterval(trials, successes,
confidenceLevel));
+ }
+
+ private void check(ConfidenceInterval expected,
+ ConfidenceInterval actual) {
+ final double relTol = 1.0e-6; // Reasonable relative tolerance for
floating point comparison
+ // Compare bounds using a relative tolerance
+ Assert.assertEquals(expected.getLowerBound(),
+ actual.getLowerBound(),
+ relTol * (1.0 +
Math.abs(expected.getLowerBound())));
+ Assert.assertEquals(expected.getUpperBound(),
+ actual.getUpperBound(),
+ relTol * (1.0 +
Math.abs(expected.getUpperBound())));
+ // The confidence level must be exact
+ Assert.assertEquals(expected.getConfidenceLevel(),
+ actual.getConfidenceLevel(),
+ 0.0);
+ }
}