22

double 値の 2 つの配列があるので、相関係数 (MS Excel の CORREL 関数と同じように、単一の double 値) を計算したいと考えています。C# に簡単な 1 行のソリューションはありますか?

私はすでに Meta Numerics という数学ライブラリを発見しました。この SO questionによると、それは仕事をするべきです。これは、Meta Numerics相関メソッドのドキュメントですが、取得できません。

誰かが簡単なコードスニペットまたはライブラリの使用方法の例を提供してくれませんか?

注: 最後に、カスタム実装の 1 つを使用することを余儀なくされました。ただし、この質問を読んでいる人が、これを行うための十分に文書化された C# 数学ライブラリ/フレームワークを知っている場合は、躊躇しないで回答にリンクを投稿してください。

4

6 に答える 6

33

同じインデックスの個別のリストに値を持ち、単純な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));

2 番目の方法は、独自のカスタム実装を作成することです (私のものは速度が最適化されていません)。

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;
}

使用法:

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");

もう 1 つの方法は、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
于 2013-07-03T12:25:18.690 に答える
26

Math.NET Numerics は、Correlation クラスを含む十分に文書化された数学ライブラリです。ピアソンとスピアマンのランク付けされた相関を計算します: http://numerics.mathdotnet.com/api/MathNet.Numerics.Statistics/Correlation.htm

このライブラリは、非常に自由度の高い MIT/X11 ライセンスの下で利用できます。これを使用して相関係数を計算するのは、次のように簡単です。

using MathNet.Numerics.Statistics;

...

correlation = Correlation.Pearson(arrayOfValues1, arrayOfValues2);

幸運を!

于 2014-12-03T16:45:45.283 に答える
9

ピアソンの積率相関係数を計算するには

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; 
  }
于 2013-07-03T12:50:09.857 に答える
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));
}
于 2013-07-03T12:24:33.543 に答える