public GPDApproximation(IList <double> data, FittingMethod method = FittingMethod.Pickands_SupNorm, Random rand = null) { if (data.Count < 30) { throw new ArgumentException("Insufficient data count for Pickands Balkema De Haan theorem."); } sortedData = new List <double>(data); sortedData.Sort(); int m; // Transition index switch (method) { case FittingMethod.BFGS_MSE: ApproximateExcessDistributionParametersBFGS(sortedData, out a, out c, out transitionAbscissa); // Compute the index of the closest element that is at or before u in the data int transitionIndex = sortedData.BinarySearch(transitionAbscissa); if (transitionIndex < 0) { transitionIndex = ~transitionIndex; } transitionProportion = transitionIndex * 1.0 / sortedData.Count; // Shouldn't this be + 1 here? break; case FittingMethod.Moments_MSE: ApproximateExcessDistributionParametersMoments(sortedData, out a, out c, out m); transitionProportion = (sortedData.Count - m + 1.0) / sortedData.Count; transitionAbscissa = sortedData[sortedData.Count - m]; // Convert from m to the actual transitionIndex; m is guaranteed to be > 0 break; case FittingMethod.V4: ApproximateExcessDistributionParametersV4(sortedData, out a, out c, out transitionAbscissa); int transitionIdx = sortedData.BinarySearch(transitionAbscissa); if (transitionIdx < 0) { transitionIdx = ~transitionIdx; // Now the index of the next-largest element if (transitionIdx == 0) { transitionProportion = 0; break; } transitionProportion = Interpolation.Lerp( sortedData[transitionIdx - 1], transitionIdx * 1.0 / sortedData.Count, sortedData[transitionIdx], (transitionIdx + 1) * 1.0 / sortedData.Count, transitionAbscissa); break; } transitionProportion = (transitionIdx + 1) * 1.0 / sortedData.Count; break; default: ApproximateExcessDistributionParametersPickands(sortedData, out a, out c, out m); // Write m to transitionIndex transitionProportion = (sortedData.Count - 4 * m + 1.0) / sortedData.Count; transitionAbscissa = sortedData[sortedData.Count - 4 * m]; // Convert from m to the actual transitionIndex; m is guaranteed to be > 0 break; } this.rand = rand ?? Program.rand; }
public static double Quantile(IList <double> sortedData, double q) { if (q < 0 || q > 1) { throw new ArgumentOutOfRangeException($"Desired percentile is out of range: {q}"); } if (q == 0) { return(sortedData[0]); } if (q == 1) { return(sortedData[sortedData.Count - 1]); } double product = (sortedData.Count - 1) * q; int idx = (int)product; //return data[idx + 1] * (product - idx) + data[idx] * (idx + 1 - product); return(Interpolation.Lerp(idx, sortedData[idx], idx + 1, sortedData[idx + 1], product)); }
/// <summary> /// Returns the value of the quantile function for this distribution at a given quantile /// </summary> public double Quantile(double q) { // Edge cases if (q < cumulativeDensities[0]) { return(abscissas[0]); } if (q > cumulativeDensities[cumulativeDensities.Count - 1]) { return(abscissas[abscissas.Count - 1]); } // Fast search for which elements to interpolate between int idx = cumulativeDensities.BinarySearch(q); // If q is an element of the cumulative densities list, return the corresponding abscissa if (idx > -1) { return(abscissas[idx]); } // Interpolate idx = ~idx; // idx is now the index of the next largest element of cumulative densities from q return(Interpolation.Lerp(cumulativeDensities[idx - 1], abscissas[idx - 1], cumulativeDensities[idx], abscissas[idx], q)); }
/// <summary> /// Returns the value of this distribution's CDF at the given location /// </summary> public double CumulativeDensity(double x) { // Edge cases if (x < abscissas[0]) { return(0); } if (x > abscissas[abscissas.Count - 1]) { return(1); } // Fast search for which elements to interpolate between int idx = abscissas.BinarySearch(x); // If x is an element of the abscissas, return the corresponding value if (idx > -1) { return(cumulativeDensities[idx]); } // Interpolate idx = ~idx; // idx is now the index of the next largest element of abscissas from x return(Interpolation.Lerp(abscissas[idx - 1], cumulativeDensities[idx - 1], abscissas[idx], cumulativeDensities[idx], x)); }