public void P2QuantileEstimatorTest(string testKey) { var testData = TestDataMap[testKey]; double p = testData.Probability; var sample = testData.Generate(); var estimator = new P2QuantileEstimator(p); foreach (double x in sample.Values) { estimator.AddValue(x); } double actual = estimator.GetQuantile(); double expected = SimpleQuantileEstimator.Instance.GetQuantile(sample, p); double pDelta = 0.1 + Math.Abs(p - 0.5) * 0.2 + 2.0 / testData.N; double expectedMin = SimpleQuantileEstimator.Instance.GetQuantile(sample, (p - pDelta).Clamp(0, 1)); double expectedMax = SimpleQuantileEstimator.Instance.GetQuantile(sample, (p + pDelta).Clamp(0, 1)); double mad = MedianAbsoluteDeviation.CalcMad(sample); double error = Math.Abs(actual - expected); double errorNorm = error / mad; output.WriteLine($"ExpectedMin = {expectedMin:N5}"); output.WriteLine($"Expected = {expected:N5}"); output.WriteLine($"ExpectedMax = {expectedMax:N5}"); output.WriteLine($"Actual = {actual:N5}"); output.WriteLine($"Error = {error:N5}"); output.WriteLine($"ErrorNorm = {errorNorm:N5}"); Assert.True(expectedMin <= actual && actual <= expectedMax); }
public override double GetValue(Sample a, Sample b, Probability probability) { Assertion.NotNull(nameof(a), a); Assertion.NotNull(nameof(b), b); try { double aMad = MedianAbsoluteDeviation.CalcMad(a); double bMad = MedianAbsoluteDeviation.CalcMad(b); if (aMad < Eps && bMad < Eps) { double aMedian = QuantileEstimator.GetMedian(a); double bMedian = QuantileEstimator.GetMedian(b); if (Math.Abs(aMedian - bMedian) < Eps) { return(0); } return(aMedian < bMedian ? double.PositiveInfinity : double.NegativeInfinity); } double aQuantile = QuantileEstimator.GetQuantile(a, probability); double bQuantile = QuantileEstimator.GetQuantile(b, probability); double pooledMad = PooledMad(a.Count, b.Count, aMad, bMad); return((bQuantile - aQuantile) / pooledMad); } catch (Exception) { return(double.NaN); } }
private MadOutlierDetector([NotNull] Sample sample, double k, double consistencyConstant, [CanBeNull] IQuantileEstimator quantileEstimator) { Assertion.NotNull(nameof(sample), sample); quantileEstimator ??= HarrellDavisQuantileEstimator.Instance; double median = quantileEstimator.GetMedian(sample); double mad = MedianAbsoluteDeviation.CalcMad(sample, consistencyConstant, quantileEstimator); LowerFence = median - k * mad; UpperFence = median + k * mad; }
public override double[] GetValues(Sample a, Sample b, IReadOnlyList <Probability> probabilities) { Assertion.NotNull(nameof(a), a); Assertion.NotNull(nameof(b), b); Assertion.NotNullOrEmpty(nameof(probabilities), probabilities); int k = probabilities.Count; try { double aMad = MedianAbsoluteDeviation.CalcMad(a); double bMad = MedianAbsoluteDeviation.CalcMad(b); if (aMad < Eps && bMad < Eps) { double aMedian = QuantileEstimator.GetMedian(a); double bMedian = QuantileEstimator.GetMedian(b); if (Math.Abs(aMedian - bMedian) < Eps) { return(ConstantSequence.Zero.GenerateArray(k)); } return(aMedian < bMedian ? ConstantSequence.PositiveInfinity.GenerateArray(k) : ConstantSequence.NegativeInfinity.GenerateArray(k)); } double[] aQuantile = QuantileEstimator.GetQuantiles(a, probabilities); double[] bQuantile = QuantileEstimator.GetQuantiles(b, probabilities); double pooledMad = PooledMad(a.Count, b.Count, aMad, bMad); double[] values = new double[k]; for (int i = 0; i < k; i++) { values[i] = (bQuantile[i] - aQuantile[i]) / pooledMad; } return(values); } catch (Exception) { return(ConstantSequence.NaN.GenerateArray(k)); } }