C#中两个数组的相关性

tee*_*jay 19 .net c# arrays correlation

有两个double值数组,我想计算相关系数(单个double值,就像MS Excel中的CORREL函数一样).C#中有一些简单的单行解决方案吗?

我已经发现了名为Meta Numerics的数学库.根据这个问题,它应该做的工作.是Meta Numerics相关方法的文档,我没有得到.

可以请某人为我提供简单的代码片段或示例如何使用该库?

注意:最后,我被迫使用一种自定义实现.但是,如果有人在阅读这个问题时知道好的,有良好记录的C#数学库/框架来做到这一点,请不要犹豫,并在回答中发布一个链接.

Dus*_*gen 28

您可以将值放在相同索引的单独列表中,并使用简单的值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));
Run Code Online (Sandbox Code Playgroud)

第二种方法是编写自己的自定义实现(我的速度并未优化):

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;
}
Run Code Online (Sandbox Code Playgroud)

用法:

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");
Run Code Online (Sandbox Code Playgroud)

另一种方法是直接使用Excel函数:

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
Run Code Online (Sandbox Code Playgroud)


Rub*_*ron 20

Math.NET Numerics是一个记录良好的数学库,包含一个Correlation类.它计算了Pearson和Spearman排名相关性:http://numerics.mathdotnet.com/api/MathNet.Numerics.Statistics/Correlation.htm

该库可在非常自由的MIT/X11许可下使用.用它来计算相关系数很简单如下:

using MathNet.Numerics.Statistics;

...

correlation = Correlation.Pearson(arrayOfValues1, arrayOfValues2);
Run Code Online (Sandbox Code Playgroud)

祝好运!


Dmi*_*nko 8

为了计算Pearson乘积矩相关系数

http://en.wikipedia.org/wiki/Pearson_product-moment_correlation_coefficient

你可以使用这个简单的代码:

  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; 
  }
Run Code Online (Sandbox Code Playgroud)


key*_*rdP 6

如果您不想使用第三方库,可以使用此帖子中的方法(在此处发布代码进行备份).

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));
}
Run Code Online (Sandbox Code Playgroud)