From d3ec8750117014916527c65e87f6b2570f93673c Mon Sep 17 00:00:00 2001 From: Christoph Ruegg Date: Sat, 12 Dec 2015 09:48:56 +0100 Subject: [PATCH] Statistics: single precision support on Covariance #235 --- src/Numerics/Statistics/ArrayStatistics.cs | 72 +++++++++++++++++-- src/Numerics/Statistics/Statistics.cs | 32 +++++++++ .../Statistics/StreamingStatistics.cs | 24 +++++++ 3 files changed, 122 insertions(+), 6 deletions(-) diff --git a/src/Numerics/Statistics/ArrayStatistics.cs b/src/Numerics/Statistics/ArrayStatistics.cs index b3827bd2..590bc016 100644 --- a/src/Numerics/Statistics/ArrayStatistics.cs +++ b/src/Numerics/Statistics/ArrayStatistics.cs @@ -434,9 +434,9 @@ namespace MathNet.Numerics.Statistics return double.NaN; } - var mean1 = Mean(samples1); - var mean2 = Mean(samples2); - var covariance = 0.0; + double mean1 = Mean(samples1); + double mean2 = Mean(samples2); + double covariance = 0.0; for (int i = 0; i < samples1.Length; i++) { covariance += (samples1[i] - mean1)*(samples2[i] - mean2); @@ -445,6 +445,36 @@ namespace MathNet.Numerics.Statistics return covariance/(samples1.Length - 1); } + /// + /// Estimates the unbiased population covariance from the provided two sample arrays. + /// On a dataset of size N will use an N-1 normalizer (Bessel's correction). + /// Returns NaN if data has less than two entries or if any entry is NaN. + /// + /// First sample array. + /// Second sample array. + public static double Covariance(float[] samples1, float[] samples2) + { + if (samples1.Length != samples2.Length) + { + throw new ArgumentException(Resources.ArgumentVectorsSameLength); + } + + if (samples1.Length <= 1) + { + return double.NaN; + } + + double mean1 = Mean(samples1); + double mean2 = Mean(samples2); + double covariance = 0.0; + for (int i = 0; i < samples1.Length; i++) + { + covariance += (samples1[i] - mean1) * (samples2[i] - mean2); + } + + return covariance / (samples1.Length - 1); + } + /// /// Evaluates the population covariance from the full population provided as two arrays. /// On a dataset of size N will use an N normalizer and would thus be biased if applied to a subset. @@ -464,9 +494,9 @@ namespace MathNet.Numerics.Statistics return double.NaN; } - var mean1 = Mean(population1); - var mean2 = Mean(population2); - var covariance = 0.0; + double mean1 = Mean(population1); + double mean2 = Mean(population2); + double covariance = 0.0; for (int i = 0; i < population1.Length; i++) { covariance += (population1[i] - mean1)*(population2[i] - mean2); @@ -475,6 +505,36 @@ namespace MathNet.Numerics.Statistics return covariance/population1.Length; } + /// + /// Evaluates the population covariance from the full population provided as two arrays. + /// On a dataset of size N will use an N normalizer and would thus be biased if applied to a subset. + /// Returns NaN if data is empty or if any entry is NaN. + /// + /// First population array. + /// Second population array. + public static double PopulationCovariance(float[] population1, float[] population2) + { + if (population1.Length != population2.Length) + { + throw new ArgumentException(Resources.ArgumentVectorsSameLength); + } + + if (population1.Length == 0) + { + return double.NaN; + } + + double mean1 = Mean(population1); + double mean2 = Mean(population2); + double covariance = 0.0; + for (int i = 0; i < population1.Length; i++) + { + covariance += (population1[i] - mean1) * (population2[i] - mean2); + } + + return covariance / population1.Length; + } + /// /// Estimates the root mean square (RMS) also known as quadratic mean from the unsorted data array. /// Returns NaN if data is empty or any entry is NaN. diff --git a/src/Numerics/Statistics/Statistics.cs b/src/Numerics/Statistics/Statistics.cs index ae6fb487..0134e070 100644 --- a/src/Numerics/Statistics/Statistics.cs +++ b/src/Numerics/Statistics/Statistics.cs @@ -508,6 +508,22 @@ namespace MathNet.Numerics.Statistics : StreamingStatistics.Covariance(samples1, samples2); } + /// + /// Estimates the unbiased population covariance from the provided samples. + /// On a dataset of size N will use an N-1 normalizer (Bessel's correction). + /// Returns NaN if data has less than two entries or if any entry is NaN. + /// + /// A subset of samples, sampled from the full population. + /// A subset of samples, sampled from the full population. + public static double Covariance(this IEnumerable samples1, IEnumerable samples2) + { + var array1 = samples1 as float[]; + var array2 = samples2 as float[]; + return array1 != null && array2 != null + ? ArrayStatistics.Covariance(array1, array2) + : StreamingStatistics.Covariance(samples1, samples2); + } + /// /// Estimates the unbiased population covariance from the provided samples. /// On a dataset of size N will use an N-1 normalizer (Bessel's correction). @@ -537,6 +553,22 @@ namespace MathNet.Numerics.Statistics : StreamingStatistics.PopulationCovariance(population1, population2); } + /// + /// Evaluates the population covariance from the provided full populations. + /// On a dataset of size N will use an N normalizer and would thus be biased if applied to a subset. + /// Returns NaN if data is empty or if any entry is NaN. + /// + /// The full population data. + /// The full population data. + public static double PopulationCovariance(this IEnumerable population1, IEnumerable population2) + { + var array1 = population1 as float[]; + var array2 = population2 as float[]; + return array1 != null && array2 != null + ? ArrayStatistics.PopulationCovariance(array1, array2) + : StreamingStatistics.PopulationCovariance(population1, population2); + } + /// /// Evaluates the population covariance from the provided full populations. /// On a dataset of size N will use an N normalize and would thus be biased if applied to a subset. diff --git a/src/Numerics/Statistics/StreamingStatistics.cs b/src/Numerics/Statistics/StreamingStatistics.cs index ddd67c08..f258e915 100644 --- a/src/Numerics/Statistics/StreamingStatistics.cs +++ b/src/Numerics/Statistics/StreamingStatistics.cs @@ -448,6 +448,18 @@ namespace MathNet.Numerics.Statistics return n > 1 ? comoment/(n - 1) : double.NaN; } + /// + /// Estimates the unbiased population covariance from the provided two sample enumerable sequences, in a single pass without memoization. + /// On a dataset of size N will use an N-1 normalizer (Bessel's correction). + /// Returns NaN if data has less than two entries or if any entry is NaN. + /// + /// First sample stream. + /// Second sample stream. + public static double Covariance(IEnumerable samples1, IEnumerable samples2) + { + return Covariance(samples1.Select(x => (double)x), samples2.Select(x => (double)x)); + } + /// /// Evaluates the population covariance from the full population provided as two enumerable sequences, in a single pass without memoization. /// On a dataset of size N will use an N normalizer and would thus be biased if applied to a subset. @@ -489,6 +501,18 @@ namespace MathNet.Numerics.Statistics return comoment/n; } + /// + /// Evaluates the population covariance from the full population provided as two enumerable sequences, in a single pass without memoization. + /// On a dataset of size N will use an N normalizer and would thus be biased if applied to a subset. + /// Returns NaN if data is empty or if any entry is NaN. + /// + /// First population stream. + /// Second population stream. + public static double PopulationCovariance(IEnumerable population1, IEnumerable population2) + { + return PopulationCovariance(population1.Select(x => (double)x), population2.Select(x => (double)x)); + } + /// /// Estimates the root mean square (RMS) also known as quadratic mean from the enumerable, in a single pass without memoization. /// Returns NaN if data is empty or any entry is NaN.