///
/// 二つの集合の相関係数を求める。二つのシーケンスの先頭から順番にペアとして要素を取り出し、要素数の多いシーケンスの残りの要素は無視される。
/// 計算式にはピアソンの積率相関係数を用いている。
/// 例外: ArgumentNullException 引数がnullシーケンス。
/// DivideByZeroException 引数が空のシーケンス。
///
/// 集合1
/// 集合2
/// 相関係数
public static double CorrelationCoefficient(this IEnumerable List1, IEnumerable List2)
{
if (List1 == null)
throw new ArgumentNullException("引数List1がnullです。");
if (List2 == null)
throw new ArgumentNullException("引数List2がnullです。");
var calcMember = List1.Zip(List2, (x, y) => new { x, y }).ToArray();
//入力された二つのシーケンスを合流して、(x, y)の一対のデーターになった配列に変換する。
//多い方の余った要素は無視される。
if (calcMember.Length == 0)
{
//要素数がゼロなら例外発生。
StringBuilder sb = new StringBuilder("計算する要素数がゼロです。");
if (List1.Count() == 0)
sb.Append("引数List1が空のシーケンスです。");
if (List1.Count() == 0)
sb.Append("引数List2が空のシーケンスです。");
throw new DivideByZeroException(sb.ToString());
}
///ピアソンの積率相関係数を計算
/// SIGMA((xi-ax)(yi-ay)) / SQRT(SIGMA((xi-ax)^2) / SQRT(SIGMA((yi-ya)^2))
var ax = calcMember.Select(r => r.x).Average();
var ay = calcMember.Select(r => r.y).Average();
var result = calcMember
.Select(r => new { xi = r.x - ax, yi = r.y - ay })
.Select(r => new { a = r.xi * r.yi, b = r.xi * r.xi, c = r.yi * r.yi })
.Aggregate((t, i) => new { a = t.a + i.a, b = t.b + i.b, c = t.c + i.c });
return result.a / Math.Sqrt(result.b) / Math.Sqrt(result.c);
}