pearsonCorrelation function

double pearsonCorrelation(
  1. List<num> x,
  2. List<num> y
)

Pearson correlation between x and y. Returns value in -1, 1 or NaN if insufficient data.

Implementation

double pearsonCorrelation(List<num> x, List<num> y) {
  if (x.length != y.length || x.length < 2) return double.nan;
  final int n = x.length;
  double sumX = 0, sumY = 0, sumXX = 0, sumYY = 0, sumXY = 0;
  for (int i = 0; i < n; i++) {
    final double xVal = x[i].toDouble();
    final double yVal = y[i].toDouble();
    sumX += xVal;
    sumY += yVal;
    final double xValSq = pow(xVal, 2).toDouble();
    final double yValSq = pow(yVal, 2).toDouble();
    sumXX += xValSq;
    sumYY += yValSq;
    sumXY += xVal * yVal;
  }
  final double nDouble = n.toDouble();
  final double sumXSq = pow(sumX, 2).toDouble();
  final double sumYSq = pow(sumY, 2).toDouble();
  // Single-pass computational form: r = cov(x,y) / (sd(x)*sd(y)) rewritten in
  // terms of raw sums so the data is traversed only once. The numerator is the
  // unnormalized covariance; the denominator factors are the unnormalized variances.
  final double numerator = sumXY - sumX * sumY / nDouble;
  final double denominator = (sumXX - sumXSq / nDouble) * (sumYY - sumYSq / nDouble);
  // Zero or negative denominator means a constant series (zero variance) or
  // floating-point underflow; correlation is undefined, so return NaN.
  if (denominator <= 0) return double.nan;
  final double r = numerator / sqrt(denominator);
  // Rounding in the running sums can nudge r just past ±1; clamp to the valid range.
  return r.clamp(-1.0, 1.0);
}