示例#1
0
        /// <summary>
        /// Estimates the specified quantile
        /// </summary>
        /// <param name="quantile">The quantile to esimtate. Must be between 0 and 1.</param>
        /// <returns>The value for the estimated quantile</returns>
        public double Quantile(double quantile)
        {
            if (quantile < 0 || quantile > 1)
            {
                throw new ArgumentOutOfRangeException("Quantile must be between 0 and 1");
            }

            if (_centroids.Count == 0)
            {
                throw new InvalidOperationException("Cannot call Quantile() method until first Adding values to the digest");
            }

            if (_centroids.Count == 1)
            {
                return(_centroids.First().Value.Mean);
            }

            int      i    = 0;
            double   t    = 0;
            double   q    = quantile * _count;
            Centroid last = null;

            foreach (Centroid centroid in _centroids.Values)
            {
                last = centroid;
                double k = centroid.Count;

                if (q < t + k)
                {
                    double delta;
                    if (i == 0)
                    {
                        Centroid successor = _centroids.Successor(centroid.Mean).Value;
                        delta = successor.Mean - centroid.Mean;
                    }
                    else if (i == _centroids.Count - 1)
                    {
                        Centroid predecessor = _centroids.Predecessor(centroid.Mean).Value;
                        delta = centroid.Mean - predecessor.Mean;
                    }
                    else
                    {
                        Centroid successor   = _centroids.Successor(centroid.Mean).Value;
                        Centroid predecessor = _centroids.Predecessor(centroid.Mean).Value;
                        delta = (successor.Mean - predecessor.Mean) / 2;
                    }

                    double estimated = centroid.Mean + ((q - t) / k - .5) * delta;

                    // If estimated value is higher than max, return max
                    return(Math.Min(estimated, this.Max));
                }

                t += k;
                i++;
            }

            return(last.Mean);
        }
示例#2
0
        private IEnumerable <Centroid> GetClosestCentroids(double x)
        {
            C5.KeyValuePair <double, Centroid> successor;
            C5.KeyValuePair <double, Centroid> predecessor;

            if (!_centroids.TryWeakSuccessor(x, out successor))
            {
                yield return(_centroids.Predecessor(x).Value);

                yield break;
            }

            if (successor.Value.Mean == x || !_centroids.TryPredecessor(x, out predecessor))
            {
                yield return(successor.Value);

                yield break;
            }

            double sDiff = Math.Abs(successor.Value.Mean - x);
            double pDiff = Math.Abs(successor.Value.Mean - x);

            if (sDiff < pDiff)
            {
                yield return(successor.Value);
            }
            else if (pDiff < sDiff)
            {
                yield return(predecessor.Value);
            }
            else
            {
                yield return(successor.Value);

                yield return(predecessor.Value);
            }
        }