예제 #1
0
        /// <summary>
        /// Calculates a Variance of a sample (set of numbers).
        /// </summary>
        /// <remarks>
        /// https://en.wikipedia.org/wiki/Variance
        /// Variance measures how far the set of numbers are spread out.
        /// Variance == 0 indicates that all numbers are identical.
        /// Variance is always non-negative.
        /// Variance close to 0 indicates that the numbers tend to be very close to the mean (and hence to each other).
        /// </remarks>
        /// <param name="samples">array of samples</param>
        /// <param name="mode">calculation mode (biased or unbiased)</param>
        /// <param name="algorithm">algorithm to use for calculations</param>
        public static VarianceInfo Calculate(IReadOnlyList<double> samples, VarianceMode mode, VarianceAlgorithm algorithm)
        {
            if (mode == VarianceMode.Biased && samples.Count <= 0)
                return VarianceInfo.NaN;
            else if (mode == VarianceMode.Unbiased && samples.Count <= 1)
                return VarianceInfo.NaN;

            //# https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance

            var partial_variance_info = new VarianceInfo();

            if (algorithm == VarianceAlgorithm.Online)
                partial_variance_info = M1M2_OnlineAlgorithm(samples);
            else if (algorithm == VarianceAlgorithm.SumsAndSumSquares)
                partial_variance_info = M1M2_SumsAndSquares(samples);
            else if (algorithm == VarianceAlgorithm.SumsAndSumSquaresWithShift)
                partial_variance_info = M1M2_SumsAndSumSquaresWithShift(samples);
            else
                throw new NotSupportedException($"{algorithm} is not supported");

            if (mode == VarianceMode.Biased)
                partial_variance_info.M2Denominator = samples.Count;
            else
                partial_variance_info.M2Denominator = (samples.Count - 1);

            return partial_variance_info;
        }
예제 #2
0
        static IObservable<VarianceInfo> M1M2_SumsAndSquares(IObservable<double> samples)
        {
            // sum of samples
            var sum_x = 0.0;

            // sum of sample squares
            var sum_x2 = 0.0;

            var m1m2 = new VarianceInfo();

            return samples.Select(x =>
            {
                sum_x += x;
                sum_x2 += x * x;

                m1m2.Count++;
                m1m2.M1 = sum_x / m1m2.Count;
                m1m2.M2 = ((sum_x * sum_x) / m1m2.Count);

                return m1m2;
            });
        }
예제 #3
0
        /// <summary>
        /// Calculates a Variance of a sample (set of numbers).
        /// </summary>
        /// <remarks>
        /// https://en.wikipedia.org/wiki/Variance
        /// Variance measures how far the set of numbers are spread out.
        /// Variance == 0 indicates that all numbers are identical.
        /// Variance is always non-negative.
        /// Variance close to 0 indicates that the numbers tend to be very close to the mean (and hence to each other).
        /// </remarks>
        /// <param name="samples">observable samples</param>
        /// <param name="mode">calculation mode (biased or unbiased)</param>
        /// <param name="algorithm">algorithm to use for calculations</param>
        public static IObservable<VarianceInfo> Calculate(IObservable<double> samples, VarianceMode mode, VarianceAlgorithm algorithm)
        {
            return Observable.Create<VarianceInfo>(o =>
            {
                var count = 0;
                VarianceInfo m1m2 = new VarianceInfo();

                var M2_Observable = (IObservable<VarianceInfo>)null;

                if (algorithm == VarianceAlgorithm.Online)
                    M2_Observable = M1M2_OnlineAlgorithm(samples);
                else
                    throw new NotSupportedException($"{algorithm} is not supported");

                M2_Observable.Subscribe(M2 =>
                {
                    count++;

                    if (mode == VarianceMode.Biased && count <= 0)
                    {
                        m1m2 = VarianceInfo.NaN;
                        o.OnNext(m1m2);
                        return;
                    }
                    else if (mode == VarianceMode.Unbiased && count <= 1)
                    {
                        m1m2 = VarianceInfo.NaN;
                        o.OnNext(m1m2);
                        return;
                    }

                    if (mode == VarianceMode.Biased)
                        m1m2.M2Denominator = count;
                    else
                        m1m2.M2Denominator = (count - 1);

                    o.OnNext(m1m2);
                });

                return Disposable.Empty;
            });
        }
예제 #4
0
        static IObservable<VarianceInfo> M1M2_OnlineAlgorithm(IObservable<double> samples)
        {
            var m1m2 = new VarianceInfo();

            return samples.Select(x =>
            {
                m1m2.Count++;
                var delta = x - m1m2.M1;
                m1m2.M1 += delta / m1m2.Count;
                m1m2.M2 += delta * (x - m1m2.M1);

                return m1m2;
            });
        }
예제 #5
0
 static VarianceInfo()
 {
     NaN = new VarianceInfo(0, double.NaN, double.NaN, double.NaN);
 }