C# Math: coefficient of variation

      Comments Off on C# Math: coefficient of variation

Just a short one again. This time I will explain the coefficient of variation. And once again give you a full code example of how you can implement it in c#.

The coefficient of variation (CV) is a normalized measure of dispersion. It is a measure of consistency indicating the uniformity in the values of the signal from the mean of the signal. A smaller coefficient of variation indicates a more consistent signal. The values are more uniformly dispersed.

Coefficient of variation is useful when comparing data with different units. For example in the SoapSynergy project I am working on I often have to make comparisons between displacement and angles. Since those signals have different units ((centi)meters versus degrees) it is useful to have a dimensionless number to compare with.

The downside of the coefficient of variation is that it is quite sensitive to changes in the mean. So if your signal moves around the 0 (as a sine wave does) making your mean ~=0, the coefficient of variation can quickly jump to near infinite numbers rendering it useless. For this reason I chose to calculate the coefficient of variation using the absolute values of my signals.

using System;
using System.Collections.Generic;

namespace SampleApp
{
    internal static class Program
    {
        private const float CompareIsZeroTolerance = 0.000000000001f;

        private static void Main()
        {
            List<double> data = new List<double> {1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2};

            double mean = data.Mean();
            double sd = data.StandardDeviation();

            double cv = CoefficientOfVariance(sd, mean);

            Console.WriteLine("CV: {0}, (mean: {1}, sd: {2})", cv, mean, sd);

            Console.WriteLine("Press any key to continue...");
            Console.ReadKey();
        }

        private static double CoefficientOfVariance(double sd, double mean)
        {
            if (Math.Abs(mean - 0) < CompareIsZeroTolerance) return 0;
            return sd / mean;
        }
    }

    public static class MyListExtensions
    {
        public static double Mean(this List<double> values)
        {
            return values.Count == 0 ? 0 : values.Mean(0, values.Count);
        }

        private static double Mean(this IList<double> values, int start, int end)
        {
            double s = 0;

            for (int i = start; i < end; i++)
            {
                s += values[i];
            }

            return s / (end - start);
        }

        private static double Variance(this IList<double> values, double mean, int start, int end)
        {
            double variance = 0;
            int i;
            for (i = start; i < end; i++)
            {
                variance += Math.Pow((values[i] - mean), 2);
            }

            int n = end - start;
            if (start > 0) n -= 1;
            return variance / (n);
        }

        public static double StandardDeviation(this List<double> values)
        {
            return values.Count == 0 ? 0 : values.StandardDeviation(0, values.Count);
        }

        private static double StandardDeviation(this IList<double> values, int start, int end)
        {
            double mean = values.Mean(start, end);
            double variance = values.Variance(mean, start, end);

            return Math.Sqrt(variance);
        }

    }
}