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
commit 9d4d838638c7ee0c6f89c8061e89ed08171ee304 Author: Gilles Sadowski <gillese...@gmail.com> AuthorDate: Mon May 31 03:37:22 2021 +0200 MATH-1431: Avoid NaN in case of empty bin. Thanks to Artem Onuchin. Closes #79. --- .../legacy/distribution/EmpiricalDistribution.java | 3 ++- .../distribution/EmpiricalDistributionTest.java | 23 +++++++++++++++++++++- src/changes/changes.xml | 3 +++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/distribution/EmpiricalDistribution.java b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/distribution/EmpiricalDistribution.java index 041f21f..4a697bb 100644 --- a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/distribution/EmpiricalDistribution.java +++ b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/distribution/EmpiricalDistribution.java @@ -743,7 +743,8 @@ public class EmpiricalDistribution extends AbstractRealDistribution * @return within-bin kernel parameterized by bStats */ protected ContinuousDistribution getKernel(SummaryStatistics bStats) { - if (bStats.getN() == 1 || bStats.getVariance() == 0) { + if (bStats.getN() <= 1 || + bStats.getVariance() == 0) { return new ConstantContinuousDistribution(bStats.getMean()); } else { return new NormalDistribution(bStats.getMean(), bStats.getStandardDeviation()); diff --git a/commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/distribution/EmpiricalDistributionTest.java b/commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/distribution/EmpiricalDistributionTest.java index dfdfdd9..5e9e650 100644 --- a/commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/distribution/EmpiricalDistributionTest.java +++ b/commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/distribution/EmpiricalDistributionTest.java @@ -24,10 +24,13 @@ import java.net.URL; import java.util.ArrayList; import java.util.Arrays; +import org.apache.commons.rng.UniformRandomProvider; +import org.apache.commons.rng.simple.RandomSource; import org.apache.commons.statistics.distribution.ContinuousDistribution; import org.apache.commons.statistics.distribution.ConstantContinuousDistribution; import org.apache.commons.statistics.distribution.UniformContinuousDistribution; import org.apache.commons.statistics.distribution.NormalDistribution; +import org.apache.commons.statistics.distribution.ExponentialDistribution; import org.apache.commons.math4.legacy.TestUtils; import org.apache.commons.math4.legacy.analysis.UnivariateFunction; import org.apache.commons.math4.legacy.analysis.integration.BaseAbstractUnivariateIntegrator; @@ -35,7 +38,6 @@ import org.apache.commons.math4.legacy.analysis.integration.IterativeLegendreGau import org.apache.commons.math4.legacy.exception.MathIllegalStateException; import org.apache.commons.math4.legacy.exception.NullArgumentException; import org.apache.commons.math4.legacy.exception.NotStrictlyPositiveException; -import org.apache.commons.rng.simple.RandomSource; import org.apache.commons.math4.legacy.stat.descriptive.SummaryStatistics; import org.apache.commons.math4.legacy.util.FastMath; import org.junit.Assert; @@ -657,6 +659,25 @@ public final class EmpiricalDistributionTest extends RealDistributionAbstractTes Assert.assertEquals(9.0, dist.inverseCumulativeProbability(0.6), tol); } + @Test + public void testMath1431() { + final UniformRandomProvider rng = RandomSource.create(RandomSource.WELL_19937_C, 1000); + final ContinuousDistribution.Sampler exponentialDistributionSampler + = new ExponentialDistribution(0.05).createSampler(rng); + final double[] empiricalDataPoints = new double[3000]; + for (int i = 0; i < empiricalDataPoints.length; i++) { + empiricalDataPoints[i] = exponentialDistributionSampler.sample(); + } + + final EmpiricalDistribution testDistribution = new EmpiricalDistribution(100); + testDistribution.load(empiricalDataPoints); + + for (int i = 0; i < 1000; i++) { + final double point = rng.nextDouble(); + final double cdf = testDistribution.cumulativeProbability(point); + Assert.assertFalse("point: " + point, Double.isNaN(cdf)); + } + } /** * Empirical distribution using a constant smoothing kernel. diff --git a/src/changes/changes.xml b/src/changes/changes.xml index c8912d5..68f4c05 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -86,6 +86,9 @@ Caveat: nightmare was one of the main reasons for creating more focused components.] "> + <action dev="erans" type="fix" issue="MATH-1431" due-to="Artem Onuchin"> + "EmpiricalDistribution" handles empty bin. + </action> <action dev="erans" type="update" issue="MATH-1582"> Transforms codes moved into a dedicated maven module. </action>