Correlation of two arrays in C# - c#
Having two arrays of double values, I want to compute correlation coefficient (single double value, just like the CORREL function in MS Excel). Is there some simple one-line solution in C#?
I already discovered math lib called Meta Numerics. According to this SO question, it should do the job. Here is docs for Meta Numerics correlation method, which I don't get.
Could pls somebody provide me with simple code snippet or example how to use the library?
Note: At the end, I was forced to use one of custom implementations.
But if someone reading this question knows good, well documented C#
math library/framework to do this, please don't hesitate and post a link in
answer.
You can have the values in separate lists at the same index and use a simple Zip.
var fitResult = new FitResult();
var values1 = new List<int>();
var values2 = new List<int>();
var correls = values1.Zip(values2, (v1, v2) =>
fitResult.CorrelationCoefficient(v1, v2));
A second way is to write your own custom implementation (mine isn't optimized for speed):
public double ComputeCoeff(double[] values1, double[] values2)
{
if(values1.Length != values2.Length)
throw new ArgumentException("values must be the same length");
var avg1 = values1.Average();
var avg2 = values2.Average();
var sum1 = values1.Zip(values2, (x1, y1) => (x1 - avg1) * (y1 - avg2)).Sum();
var sumSqr1 = values1.Sum(x => Math.Pow((x - avg1), 2.0));
var sumSqr2 = values2.Sum(y => Math.Pow((y - avg2), 2.0));
var result = sum1 / Math.Sqrt(sumSqr1 * sumSqr2);
return result;
}
Usage:
var values1 = new List<double> { 3, 2, 4, 5 ,6 };
var values2 = new List<double> { 9, 7, 12 ,15, 17 };
var result = ComputeCoeff(values1.ToArray(), values2.ToArray());
// 0.997054485501581
Debug.Assert(result.ToString("F6") == "0.997054");
Another way is to use the Excel function directly:
var values1 = new List<double> { 3, 2, 4, 5 ,6 };
var values2 = new List<double> { 9, 7, 12 ,15, 17 };
// Make sure to add a reference to Microsoft.Office.Interop.Excel.dll
// and use the namespace
var application = new Application();
var worksheetFunction = application.WorksheetFunction;
var result = worksheetFunction.Correl(values1.ToArray(), values2.ToArray());
Console.Write(result); // 0.997054485501581
Math.NET Numerics is a well-documented math library that contains a Correlation class. It calculates Pearson and Spearman ranked correlations: http://numerics.mathdotnet.com/api/MathNet.Numerics.Statistics/Correlation.htm
The library is available under the very liberal MIT/X11 license. Using it to calculate a correlation coefficient is as easy as follows:
using MathNet.Numerics.Statistics;
...
correlation = Correlation.Pearson(arrayOfValues1, arrayOfValues2);
Good luck!
In order to calculate Pearson product-moment correlation coefficient
http://en.wikipedia.org/wiki/Pearson_product-moment_correlation_coefficient
You can use this simple code:
public static Double Correlation(Double[] Xs, Double[] Ys) {
Double sumX = 0;
Double sumX2 = 0;
Double sumY = 0;
Double sumY2 = 0;
Double sumXY = 0;
int n = Xs.Length < Ys.Length ? Xs.Length : Ys.Length;
for (int i = 0; i < n; ++i) {
Double x = Xs[i];
Double y = Ys[i];
sumX += x;
sumX2 += x * x;
sumY += y;
sumY2 += y * y;
sumXY += x * y;
}
Double stdX = Math.Sqrt(sumX2 / n - sumX * sumX / n / n);
Double stdY = Math.Sqrt(sumY2 / n - sumY * sumY / n / n);
Double covariance = (sumXY / n - sumX * sumY / n / n);
return covariance / stdX / stdY;
}
If you don't want to use a third party library, you can use the method from this post (posting code here for backup).
public double Correlation(double[] array1, double[] array2)
{
double[] array_xy = new double[array1.Length];
double[] array_xp2 = new double[array1.Length];
double[] array_yp2 = new double[array1.Length];
for (int i = 0; i < array1.Length; i++)
array_xy[i] = array1[i] * array2[i];
for (int i = 0; i < array1.Length; i++)
array_xp2[i] = Math.Pow(array1[i], 2.0);
for (int i = 0; i < array1.Length; i++)
array_yp2[i] = Math.Pow(array2[i], 2.0);
double sum_x = 0;
double sum_y = 0;
foreach (double n in array1)
sum_x += n;
foreach (double n in array2)
sum_y += n;
double sum_xy = 0;
foreach (double n in array_xy)
sum_xy += n;
double sum_xpow2 = 0;
foreach (double n in array_xp2)
sum_xpow2 += n;
double sum_ypow2 = 0;
foreach (double n in array_yp2)
sum_ypow2 += n;
double Ex2 = Math.Pow(sum_x, 2.00);
double Ey2 = Math.Pow(sum_y, 2.00);
return (array1.Length * sum_xy - sum_x * sum_y) /
Math.Sqrt((array1.Length * sum_xpow2 - Ex2) * (array1.Length * sum_ypow2 - Ey2));
}
In my tests, both #Dmitry Bychenko's and #keyboardP's code postings above resulted in generally the same correlations as Microsoft Excel over a handful of manual tests I did, and did not need any external libraries.
e.g. Running this once (data for this run listed at the bottom):
#Dmitry Bychenko: -0.00418479432051121
#keyboardP:______-0.00418479432051131
MS Excel:_________-0.004184794
Here is a test harness:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestCorrel {
class Program {
static void Main(string[] args) {
Random rand = new Random(DateTime.Now.Millisecond);
List<double> x = new List<double>();
List<double> y = new List<double>();
for (int i = 0; i < 100; i++) {
x.Add(rand.Next(1000) * rand.NextDouble());
y.Add(rand.Next(1000) * rand.NextDouble());
Console.WriteLine(x[i] + "," + y[i]);
}
Console.WriteLine("Correl1: " + Correl1(x, y));
Console.WriteLine("Correl2: " + Correl2(x, y));
}
public static double Correl1(List<double> x, List<double> y) {
//https://stackoverflow.com/questions/17447817/correlation-of-two-arrays-in-c-sharp
if (x.Count != y.Count)
return (double.NaN); //throw new ArgumentException("values must be the same length");
double sumX = 0;
double sumX2 = 0;
double sumY = 0;
double sumY2 = 0;
double sumXY = 0;
int n = x.Count < y.Count ? x.Count : y.Count;
for (int i = 0; i < n; ++i) {
Double xval = x[i];
Double yval = y[i];
sumX += xval;
sumX2 += xval * xval;
sumY += yval;
sumY2 += yval * yval;
sumXY += xval * yval;
}
Double stdX = Math.Sqrt(sumX2 / n - sumX * sumX / n / n);
Double stdY = Math.Sqrt(sumY2 / n - sumY * sumY / n / n);
Double covariance = (sumXY / n - sumX * sumY / n / n);
return covariance / stdX / stdY;
}
public static double Correl2(List<double> x, List<double> y) {
double[] array_xy = new double[x.Count];
double[] array_xp2 = new double[x.Count];
double[] array_yp2 = new double[x.Count];
for (int i = 0; i < x.Count; i++)
array_xy[i] = x[i] * y[i];
for (int i = 0; i < x.Count; i++)
array_xp2[i] = Math.Pow(x[i], 2.0);
for (int i = 0; i < x.Count; i++)
array_yp2[i] = Math.Pow(y[i], 2.0);
double sum_x = 0;
double sum_y = 0;
foreach (double n in x)
sum_x += n;
foreach (double n in y)
sum_y += n;
double sum_xy = 0;
foreach (double n in array_xy)
sum_xy += n;
double sum_xpow2 = 0;
foreach (double n in array_xp2)
sum_xpow2 += n;
double sum_ypow2 = 0;
foreach (double n in array_yp2)
sum_ypow2 += n;
double Ex2 = Math.Pow(sum_x, 2.00);
double Ey2 = Math.Pow(sum_y, 2.00);
double Correl =
(x.Count * sum_xy - sum_x * sum_y) /
Math.Sqrt((x.Count * sum_xpow2 - Ex2) * (x.Count * sum_ypow2 - Ey2));
return (Correl);
}
}
}
Data for the example numbers above:
287.688269702572,225.610842817282
618.9313498167,177.955550192835
25.7778882802361,27.6549569366756
140.847984766051,714.618547504125
438.618761728806,533.48764902702
481.347431274758,214.381256273194
21.6406916848573,393.559209519792
135.30397563209,158.419851317732
334.314685154853,814.275162949821
764.614904770914,50.1435267264692
42.8179292282173,47.8631582287434
237.216836650491,370.488416981179
388.849658539449,134.961087643151
305.903013161804,441.926902444068
10.6625048679591,369.567569480076
36.9316453891488,24.8947204607049
2.10067253471383,491.941975629861
7.94887068492774,573.037801189831
341.738006353722,653.497146697015
98.8424873439793,475.215988045193
272.248712629196,36.1088809138671
122.336823399801,169.158256422336
9.32281673202422,631.076001565473
201.118425176068,803.724831627554
415.514343714115,64.248651454341
227.791637123,230.512133914284
25.3438658925443,396.854282886188
596.238994411304,72.543763144195
230.239735877253,933.983901697669
796.060099040186,689.952468971234
9.30882684202344,269.22063744125
16.5005430148451,8.96549091859045
536.324005148524,358.829873788557
519.694526420764,17.3212184707267
552.628357889423,12.5541588051962
210.516099897454,388.57537739937
141.341571405689,268.082028986924
503.880356335491,753.447006912645
515.494990213539,444.451280259737
973.8670776076,168.922799013985
85.7111146094795,36.3784999169309
37.2147129193017,108.040356312432
504.590177939548,50.3934166889607
482.821039277511,888.984586256083
5.52549206350255,156.717087003271
405.833169031345,394.099059180868
459.249365587835,11.68776424494
429.421127440604,314.216759666901
126.908422469584,331.907062556551
62.1416232716952,3.19765723645578
4.16058817699579,604.04046284223
484.262182311277,220.177370167886
58.6774453314382,339.09660232677
463.482149892246,199.181594849183
344.128297473829,268.531428258182
0.883430369609702,209.346384477963
77.9462970131758,255.221325168955
583.629439312792,235.557751925922
358.409186083083,376.046612200349
81.2148325150902,10.7696774717279
53.7315618049966,274.171515094196
111.284646992239,130.174321939319
317.280491961763,338.077288461885
177.454564264722,7.53587801919127
69.2239431670047,233.693477620228
823.419546454875,0.111916855029723
23.7174749401014,200.989081544331
44.9598299125022,102.633862571155
74.1602278468945,292.485449988155
130.11182449251,23.4682153367755
243.088760058903,335.807090202722
13.3974915991526,436.983231269281
73.3900805168739,252.352352472186
592.144630201228,92.3395205570103
57.7306153447044,47.1416798900541
522.649018382024,584.427794722108
15.3662010204821,60.1693953262499
16.8335716728277,851.401980430541
33.9869734449251,0.930781653584345
116.66608504982,146.126050951949
92.8896130355492,711.765618208687
317.91980889529,322.186540377413
44.8574470732629,209.275617858058
751.201537871362,37.935519233316
161.817758424588,2.83156183493862
531.64078452142,79.1750782491523
114.803219681048,283.106988439852
123.472725123853,154.125248027558
89.9276725453919,63.4626924192825
105.623296753328,111.234188702067
435.72981759707,23.7058234576629
259.324810619152,69.3535200857341
719.885234421531,381.086239833891
24.2674900099018,198.408173349876
57.7761600361095,146.52277489124
77.4594609157459,710.746080866431
636.671781979814,538.894185951396
56.6035279932448,58.2563265684323
485.16099039333,427.849954283261
91.9552873247095,576.92944263617
Public Function Correlation(ByRef array1() As Double, ByRef array2() As Double) As Double
'siehe https://stackoverflow.com/questions/17447817/correlation-of-two-arrays-in-c-sharp
'der hier errechnete "Pearson correlation coefficient" muss noch quadriert werden, um R-Squared zu erhalten, siehe
'https://en.wikipedia.org/wiki/Coefficient_of_determination
Dim array_xy(array1.Length - 1) As Double
Dim array_xp2(array1.Length - 1) As Double
Dim array_yp2(array1.Length - 1) As Double
Dim i As Integer
For i = 0 To array1.Length - 1
array_xy(i) = array1(i) * array2(i)
Next i
For i = 0 To array1.Length - 1
array_xp2(i) = Math.Pow(array1(i), 2.0)
Next i
For i = 0 To array1.Length - 1
array_yp2(i) = Math.Pow(array2(i), 2.0)
Next i
Dim sum_x As Double = 0
Dim sum_y As Double = 0
Dim EinDouble As Double
For Each EinDouble In array1
sum_x += EinDouble
Next
For Each EinDouble In array2
sum_y += EinDouble
Next
Dim sum_xy As Double = 0
For Each EinDouble In array_xy
sum_xy += EinDouble
Next
Dim sum_xpow2 As Double = 0
For Each EinDouble In array_xp2
sum_xpow2 += EinDouble
Next
Dim sum_ypow2 As Double = 0
For Each EinDouble In array_yp2
sum_ypow2 += EinDouble
Next
Dim Ex2 As Double = Math.Pow(sum_x, 2.0)
Dim Ey2 As Double = Math.Pow(sum_y, 2.0)
Dim ReturnWert As Double
ReturnWert = (array1.Length * sum_xy - sum_x * sum_y) / Math.Sqrt((array1.Length * sum_xpow2 - Ex2) * (array1.Length * sum_ypow2 - Ey2))
Correlation = ReturnWert
End Function
Related
How to tell if two FFT results are similar? [duplicate]
Having two arrays of double values, I want to compute correlation coefficient (single double value, just like the CORREL function in MS Excel). Is there some simple one-line solution in C#? I already discovered math lib called Meta Numerics. According to this SO question, it should do the job. Here is docs for Meta Numerics correlation method, which I don't get. Could pls somebody provide me with simple code snippet or example how to use the library? Note: At the end, I was forced to use one of custom implementations. But if someone reading this question knows good, well documented C# math library/framework to do this, please don't hesitate and post a link in answer.
You can have the values in separate lists at the same index and use a simple Zip. var fitResult = new FitResult(); var values1 = new List<int>(); var values2 = new List<int>(); var correls = values1.Zip(values2, (v1, v2) => fitResult.CorrelationCoefficient(v1, v2)); A second way is to write your own custom implementation (mine isn't optimized for speed): public double ComputeCoeff(double[] values1, double[] values2) { if(values1.Length != values2.Length) throw new ArgumentException("values must be the same length"); var avg1 = values1.Average(); var avg2 = values2.Average(); var sum1 = values1.Zip(values2, (x1, y1) => (x1 - avg1) * (y1 - avg2)).Sum(); var sumSqr1 = values1.Sum(x => Math.Pow((x - avg1), 2.0)); var sumSqr2 = values2.Sum(y => Math.Pow((y - avg2), 2.0)); var result = sum1 / Math.Sqrt(sumSqr1 * sumSqr2); return result; } Usage: var values1 = new List<double> { 3, 2, 4, 5 ,6 }; var values2 = new List<double> { 9, 7, 12 ,15, 17 }; var result = ComputeCoeff(values1.ToArray(), values2.ToArray()); // 0.997054485501581 Debug.Assert(result.ToString("F6") == "0.997054"); Another way is to use the Excel function directly: var values1 = new List<double> { 3, 2, 4, 5 ,6 }; var values2 = new List<double> { 9, 7, 12 ,15, 17 }; // Make sure to add a reference to Microsoft.Office.Interop.Excel.dll // and use the namespace var application = new Application(); var worksheetFunction = application.WorksheetFunction; var result = worksheetFunction.Correl(values1.ToArray(), values2.ToArray()); Console.Write(result); // 0.997054485501581
Math.NET Numerics is a well-documented math library that contains a Correlation class. It calculates Pearson and Spearman ranked correlations: http://numerics.mathdotnet.com/api/MathNet.Numerics.Statistics/Correlation.htm The library is available under the very liberal MIT/X11 license. Using it to calculate a correlation coefficient is as easy as follows: using MathNet.Numerics.Statistics; ... correlation = Correlation.Pearson(arrayOfValues1, arrayOfValues2); Good luck!
In order to calculate Pearson product-moment correlation coefficient http://en.wikipedia.org/wiki/Pearson_product-moment_correlation_coefficient You can use this simple code: public static Double Correlation(Double[] Xs, Double[] Ys) { Double sumX = 0; Double sumX2 = 0; Double sumY = 0; Double sumY2 = 0; Double sumXY = 0; int n = Xs.Length < Ys.Length ? Xs.Length : Ys.Length; for (int i = 0; i < n; ++i) { Double x = Xs[i]; Double y = Ys[i]; sumX += x; sumX2 += x * x; sumY += y; sumY2 += y * y; sumXY += x * y; } Double stdX = Math.Sqrt(sumX2 / n - sumX * sumX / n / n); Double stdY = Math.Sqrt(sumY2 / n - sumY * sumY / n / n); Double covariance = (sumXY / n - sumX * sumY / n / n); return covariance / stdX / stdY; }
If you don't want to use a third party library, you can use the method from this post (posting code here for backup). public double Correlation(double[] array1, double[] array2) { double[] array_xy = new double[array1.Length]; double[] array_xp2 = new double[array1.Length]; double[] array_yp2 = new double[array1.Length]; for (int i = 0; i < array1.Length; i++) array_xy[i] = array1[i] * array2[i]; for (int i = 0; i < array1.Length; i++) array_xp2[i] = Math.Pow(array1[i], 2.0); for (int i = 0; i < array1.Length; i++) array_yp2[i] = Math.Pow(array2[i], 2.0); double sum_x = 0; double sum_y = 0; foreach (double n in array1) sum_x += n; foreach (double n in array2) sum_y += n; double sum_xy = 0; foreach (double n in array_xy) sum_xy += n; double sum_xpow2 = 0; foreach (double n in array_xp2) sum_xpow2 += n; double sum_ypow2 = 0; foreach (double n in array_yp2) sum_ypow2 += n; double Ex2 = Math.Pow(sum_x, 2.00); double Ey2 = Math.Pow(sum_y, 2.00); return (array1.Length * sum_xy - sum_x * sum_y) / Math.Sqrt((array1.Length * sum_xpow2 - Ex2) * (array1.Length * sum_ypow2 - Ey2)); }
In my tests, both #Dmitry Bychenko's and #keyboardP's code postings above resulted in generally the same correlations as Microsoft Excel over a handful of manual tests I did, and did not need any external libraries. e.g. Running this once (data for this run listed at the bottom): #Dmitry Bychenko: -0.00418479432051121 #keyboardP:______-0.00418479432051131 MS Excel:_________-0.004184794 Here is a test harness: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace TestCorrel { class Program { static void Main(string[] args) { Random rand = new Random(DateTime.Now.Millisecond); List<double> x = new List<double>(); List<double> y = new List<double>(); for (int i = 0; i < 100; i++) { x.Add(rand.Next(1000) * rand.NextDouble()); y.Add(rand.Next(1000) * rand.NextDouble()); Console.WriteLine(x[i] + "," + y[i]); } Console.WriteLine("Correl1: " + Correl1(x, y)); Console.WriteLine("Correl2: " + Correl2(x, y)); } public static double Correl1(List<double> x, List<double> y) { //https://stackoverflow.com/questions/17447817/correlation-of-two-arrays-in-c-sharp if (x.Count != y.Count) return (double.NaN); //throw new ArgumentException("values must be the same length"); double sumX = 0; double sumX2 = 0; double sumY = 0; double sumY2 = 0; double sumXY = 0; int n = x.Count < y.Count ? x.Count : y.Count; for (int i = 0; i < n; ++i) { Double xval = x[i]; Double yval = y[i]; sumX += xval; sumX2 += xval * xval; sumY += yval; sumY2 += yval * yval; sumXY += xval * yval; } Double stdX = Math.Sqrt(sumX2 / n - sumX * sumX / n / n); Double stdY = Math.Sqrt(sumY2 / n - sumY * sumY / n / n); Double covariance = (sumXY / n - sumX * sumY / n / n); return covariance / stdX / stdY; } public static double Correl2(List<double> x, List<double> y) { double[] array_xy = new double[x.Count]; double[] array_xp2 = new double[x.Count]; double[] array_yp2 = new double[x.Count]; for (int i = 0; i < x.Count; i++) array_xy[i] = x[i] * y[i]; for (int i = 0; i < x.Count; i++) array_xp2[i] = Math.Pow(x[i], 2.0); for (int i = 0; i < x.Count; i++) array_yp2[i] = Math.Pow(y[i], 2.0); double sum_x = 0; double sum_y = 0; foreach (double n in x) sum_x += n; foreach (double n in y) sum_y += n; double sum_xy = 0; foreach (double n in array_xy) sum_xy += n; double sum_xpow2 = 0; foreach (double n in array_xp2) sum_xpow2 += n; double sum_ypow2 = 0; foreach (double n in array_yp2) sum_ypow2 += n; double Ex2 = Math.Pow(sum_x, 2.00); double Ey2 = Math.Pow(sum_y, 2.00); double Correl = (x.Count * sum_xy - sum_x * sum_y) / Math.Sqrt((x.Count * sum_xpow2 - Ex2) * (x.Count * sum_ypow2 - Ey2)); return (Correl); } } } Data for the example numbers above: 287.688269702572,225.610842817282 618.9313498167,177.955550192835 25.7778882802361,27.6549569366756 140.847984766051,714.618547504125 438.618761728806,533.48764902702 481.347431274758,214.381256273194 21.6406916848573,393.559209519792 135.30397563209,158.419851317732 334.314685154853,814.275162949821 764.614904770914,50.1435267264692 42.8179292282173,47.8631582287434 237.216836650491,370.488416981179 388.849658539449,134.961087643151 305.903013161804,441.926902444068 10.6625048679591,369.567569480076 36.9316453891488,24.8947204607049 2.10067253471383,491.941975629861 7.94887068492774,573.037801189831 341.738006353722,653.497146697015 98.8424873439793,475.215988045193 272.248712629196,36.1088809138671 122.336823399801,169.158256422336 9.32281673202422,631.076001565473 201.118425176068,803.724831627554 415.514343714115,64.248651454341 227.791637123,230.512133914284 25.3438658925443,396.854282886188 596.238994411304,72.543763144195 230.239735877253,933.983901697669 796.060099040186,689.952468971234 9.30882684202344,269.22063744125 16.5005430148451,8.96549091859045 536.324005148524,358.829873788557 519.694526420764,17.3212184707267 552.628357889423,12.5541588051962 210.516099897454,388.57537739937 141.341571405689,268.082028986924 503.880356335491,753.447006912645 515.494990213539,444.451280259737 973.8670776076,168.922799013985 85.7111146094795,36.3784999169309 37.2147129193017,108.040356312432 504.590177939548,50.3934166889607 482.821039277511,888.984586256083 5.52549206350255,156.717087003271 405.833169031345,394.099059180868 459.249365587835,11.68776424494 429.421127440604,314.216759666901 126.908422469584,331.907062556551 62.1416232716952,3.19765723645578 4.16058817699579,604.04046284223 484.262182311277,220.177370167886 58.6774453314382,339.09660232677 463.482149892246,199.181594849183 344.128297473829,268.531428258182 0.883430369609702,209.346384477963 77.9462970131758,255.221325168955 583.629439312792,235.557751925922 358.409186083083,376.046612200349 81.2148325150902,10.7696774717279 53.7315618049966,274.171515094196 111.284646992239,130.174321939319 317.280491961763,338.077288461885 177.454564264722,7.53587801919127 69.2239431670047,233.693477620228 823.419546454875,0.111916855029723 23.7174749401014,200.989081544331 44.9598299125022,102.633862571155 74.1602278468945,292.485449988155 130.11182449251,23.4682153367755 243.088760058903,335.807090202722 13.3974915991526,436.983231269281 73.3900805168739,252.352352472186 592.144630201228,92.3395205570103 57.7306153447044,47.1416798900541 522.649018382024,584.427794722108 15.3662010204821,60.1693953262499 16.8335716728277,851.401980430541 33.9869734449251,0.930781653584345 116.66608504982,146.126050951949 92.8896130355492,711.765618208687 317.91980889529,322.186540377413 44.8574470732629,209.275617858058 751.201537871362,37.935519233316 161.817758424588,2.83156183493862 531.64078452142,79.1750782491523 114.803219681048,283.106988439852 123.472725123853,154.125248027558 89.9276725453919,63.4626924192825 105.623296753328,111.234188702067 435.72981759707,23.7058234576629 259.324810619152,69.3535200857341 719.885234421531,381.086239833891 24.2674900099018,198.408173349876 57.7761600361095,146.52277489124 77.4594609157459,710.746080866431 636.671781979814,538.894185951396 56.6035279932448,58.2563265684323 485.16099039333,427.849954283261 91.9552873247095,576.92944263617
Public Function Correlation(ByRef array1() As Double, ByRef array2() As Double) As Double 'siehe https://stackoverflow.com/questions/17447817/correlation-of-two-arrays-in-c-sharp 'der hier errechnete "Pearson correlation coefficient" muss noch quadriert werden, um R-Squared zu erhalten, siehe 'https://en.wikipedia.org/wiki/Coefficient_of_determination Dim array_xy(array1.Length - 1) As Double Dim array_xp2(array1.Length - 1) As Double Dim array_yp2(array1.Length - 1) As Double Dim i As Integer For i = 0 To array1.Length - 1 array_xy(i) = array1(i) * array2(i) Next i For i = 0 To array1.Length - 1 array_xp2(i) = Math.Pow(array1(i), 2.0) Next i For i = 0 To array1.Length - 1 array_yp2(i) = Math.Pow(array2(i), 2.0) Next i Dim sum_x As Double = 0 Dim sum_y As Double = 0 Dim EinDouble As Double For Each EinDouble In array1 sum_x += EinDouble Next For Each EinDouble In array2 sum_y += EinDouble Next Dim sum_xy As Double = 0 For Each EinDouble In array_xy sum_xy += EinDouble Next Dim sum_xpow2 As Double = 0 For Each EinDouble In array_xp2 sum_xpow2 += EinDouble Next Dim sum_ypow2 As Double = 0 For Each EinDouble In array_yp2 sum_ypow2 += EinDouble Next Dim Ex2 As Double = Math.Pow(sum_x, 2.0) Dim Ey2 As Double = Math.Pow(sum_y, 2.0) Dim ReturnWert As Double ReturnWert = (array1.Length * sum_xy - sum_x * sum_y) / Math.Sqrt((array1.Length * sum_xpow2 - Ex2) * (array1.Length * sum_ypow2 - Ey2)) Correlation = ReturnWert End Function
Matrix Multiplication returning wrong value
I am calculating values by using weights and bias from MATLAB trained ANN. trying to code a sigmoid simulation equation, but for some reason C# calculations vary too much than that of MATLAB. i.e. error is too high. I tried to check each step of the equation and found out the specific part that is creating the problem (Emphasized part), but I don't know how to solve this issue, if someone could help, would be a huge favour. 1+(purelin(net.LW{2}×(tansig(net.IW{1}×(1-(abs(2×([inputs]-1)))))+net.b{1}))+net.b{2}))/2 //Normalization of Data public double Normalization(double x, double xMAx, double xMin) { double xNorm = 0.0; xNorm = (x - xMin) / (xMAx - xMin); if (xNorm < 0) xNorm = 0; if (xNorm > 1) xNorm = 1; xNorm = Math.Round(xNorm, 4); return xNorm; } // Equation to calculate ANN based Output Values public double MetrixCalc(double[] Pn, double[,] W1, double[] W2, double[] b1, double b2, double maxValue, double minValue) { double FinalValue = 0; double[] PnCalc1 = new double[Pn.Length]; double[] PnCalc2 = new double[W1.Length / Pn.Length]; for (int i = 0; i < Pn.Length; i++) { PnCalc1[i] = 1 - Math.Abs(2 * (Pn[i] - 1)); } for (int i = 0; i < (W1.Length / Pn.Length); i++) { double PnCalc = 0.0; for (int j = 0; j < Pn.Length; j++) { PnCalc = PnCalc + (W1[i, j] * PnCalc1[j]); } PnCalc2[i] = PnCalc; } for (int i = 0; i < PnCalc2.Length; i++) { //PnCalc2[i] = Math.Tanh(PnCalc2[i] + b1[i]); PnCalc2[i] = PnCalc2[i] + b1[i]; PnCalc2[i] = 2.0 / (1 + Math.Exp(-2 * (PnCalc2[i]))) - 1; PnCalc2[i] = Math.Round(PnCalc2[i], 4); } double FinalCalc = 0.0; for (int i = 0; i < PnCalc2.Length; i++) { *FinalCalc = FinalCalc + (W2[i] * (PnCalc2[i]));* //FinalValue = FinalCalc; } FinalValue = FinalCalc + b2; FinalValue = 1 + FinalValue; FinalValue = (1 + FinalValue) / 2.0; FinalValue = (FinalValue * (maxValue - minValue)) + minValue; FinalValue = Math.Round(FinalValue, 4); FinalValue = Math.Abs(FinalValue); return FinalValue; }
Problem is solved. Problem was with the weights matrix copied from MATLAB. debugging mode saved my life. :)
Laplace Transform And Getting The Frequent Value For Gyro
I'm getting x,y,z values from gyro-sensor. Each variable is being sent 10 values per second. In 3 seconds I have; x=[30values] y=[30values] z=[30values] Some of the values are too different from the others cause of noise. With laplace transform I need to get the most frequent value from my array. I need to filter the array with Laplace Transform equation. I need to build the equation in C#. How can I implement the array with the equation?
Since this kind of filter (Laplace) is very specialized to certain area of Engineering and needs a person who has good understanding on both the programming language (in this case is C#) and the filter itself, I would recommend you to use such source, rather than code the filter by yourself. Here is the snippet of the source code: class Laplace { const int DefaultStehfest = 14; public delegate double FunctionDelegate(double t); static double[] V; // Stehfest coefficients static double ln2; // log of 2 public static void InitStehfest(int N) { ln2 = Math.Log(2.0); int N2 = N / 2; int NV = 2 * N2; V = new double[NV]; int sign = 1; if ((N2 % 2) != 0) sign = -1; for (int i = 0; i < NV; i++) { int kmin = (i + 2) / 2; int kmax = i + 1; if (kmax > N2) kmax = N2; V[i] = 0; sign = -sign; for (int k = kmin; k <= kmax; k++) { V[i] = V[i] + (Math.Pow(k, N2) / Factorial(k)) * (Factorial(2 * k) / Factorial(2 * k - i - 1)) / Factorial(N2 - k) / Factorial(k - 1) / Factorial(i + 1 - k); } V[i] = sign * V[i]; } } public static double InverseTransform(FunctionDelegate f, double t) { double ln2t = ln2 / t; double x = 0; double y = 0; for (int i = 0; i < V.Length; i++) { x += ln2t; y += V[i] * f(x); } return ln2t * y; } public static double Factorial(int N) { double x = 1; if (N > 1) { for (int i = 2; i <= N; i++) x = i * x; } return x; } } coded by Mr. Walt Fair Jr. in CodeProject.
Monte Carlo Pi not accurate
I am having trouble with my Monte Carlo Pi program calculating properly. Basically, pi is only displaying up to 2 decimal points only at the moment, and I feel the calculation has gone wrong somewhere as the closest pi calculation as number gets higher is 2.98-3.04. My code is pasted below. static void Main(string[] args) { double n; double count; double c = 0.0; double x = 0.0, y = 0.0; double pi; string input; Console.WriteLine("Please input a number of dots for Monte Carlo to calculate pi."); input = Console.ReadLine(); n = double.Parse(input); Random rand = new Random(); for (int i = 1; i < n; i++ ) { x = rand.Next(-1, 1); y = rand.Next(-1, 1); if (((x * x) + (y * y) <= 1)) c++; pi = 4.0 * ( c / i ); Console.WriteLine("pi: {0,-10:0.00} Dots in square: {1,-15:0} Dots in circle: {2,-20:0}", pi, i, c); } }
These calls x = rand.Next(-1, 1); y = rand.Next(-1, 1); give you an integer. But you need doubles: x = rand.NextDouble() * 2 - 1; y = rand.NextDouble() * 2 - 1;
The random numbers should be generated between 0 and 1 and not -1 and 1. Used this fixed version of your code as "mysterious code" for students. using System; namespace mysCode { class Program { static double euclideanDistance(double x1, double y1, double x2, double y2) { double dX = x2 - x1; double dY = y2 - y1; return Math.Sqrt(dX * dX + dY * dY); } static void Main(string[] args) { double n; double c = 0.0; double x = 0.0, y = 0.0; double result; string input; Console.WriteLine("Quick, pick an integer"); input = Console.ReadLine(); n = double.Parse(input); Random rand = new Random(); for (int i = 1; i <= n; i++) { x = rand.NextDouble(); y = rand.NextDouble(); if (euclideanDistance(x, y, 0, 0) <= 1) c++; result = 4.0 * (c / i); Console.WriteLine("Result: " + result); } Console.ReadKey(); } } } It coverages very slowly, I get 3.14152314152314 after 1M iterations.
How to compute ifft from fft?
I've done a fft to get fundamental frequency in real time and to implement high and low pass filters. Now I want to be able to record to a .wav file after I apply a filter. First I'll have to invert the fft and that is my question. What are the steps to do this? I use the FFT defined in this project. Here is the code for it: using System; using System.Collections.Generic; using System.Text; namespace SoundLog { public class FourierTransform { static private int n, nu; static private int BitReverse(int j) { int j2; int j1 = j; int k = 0; for (int i = 1; i <= nu; i++) { j2 = j1 / 2; k = 2 * k + j1 - 2 * j2; j1 = j2; } return k; } static public double[] FFT(ref double[] x) { // Assume n is a power of 2 n = x.Length; nu = (int)(Math.Log(n) / Math.Log(2)); int n2 = n / 2; int nu1 = nu - 1; double[] xre = new double[n]; double[] xim = new double[n]; double[] magnitude = new double[n2]; double[] decibel = new double[n2]; double tr, ti, p, arg, c, s; for (int i = 0; i < n; i++) { xre[i] = x[i]; xim[i] = 0.0f; } int k = 0; for (int l = 1; l <= nu; l++) { while (k < n) { for (int i = 1; i <= n2; i++) { p = BitReverse(k >> nu1); arg = 2 * (double)Math.PI * p / n; c = (double)Math.Cos(arg); s = (double)Math.Sin(arg); tr = xre[k + n2] * c + xim[k + n2] * s; ti = xim[k + n2] * c - xre[k + n2] * s; xre[k + n2] = xre[k] - tr; xim[k + n2] = xim[k] - ti; xre[k] += tr; xim[k] += ti; k++; } k += n2; } k = 0; nu1--; n2 = n2 / 2; } k = 0; int r; while (k < n) { r = BitReverse(k); if (r > k) { tr = xre[k]; ti = xim[k]; xre[k] = xre[r]; xim[k] = xim[r]; xre[r] = tr; xim[r] = ti; } k++; } for (int i = 0; i < n / 2; i++) //magnitude[i] = (float)(Math.Sqrt((xre[i] * xre[i]) + (xim[i] * xim[i]))); decibel[i] = 10.0 * Math.Log10((float)(Math.Sqrt((xre[i] * xre[i]) + (xim[i] * xim[i])))); //return magnitude; return decibel; } } }
There are so many really good fft implementations around such as FFTW that I highly recommend using one. They come with ifft as well. Yours, as implemented, will be excruciatingly slow.