import mean from "./mean.js";
/**
* [样本协方差](https://en.wikipedia.org/wiki/Sample_mean_and_covariance)计算两个数据集的协同变化程度:
* 评估两个数据集的变动趋势是否一致。
* x 和 y 是两个数据集,表示为数值数组。
*
* @param {Array<number>} x 至少包含两个数据点的样本数据
* @param {Array<number>} y 至少包含两个数据点的样本数据
* @throws {Error} 如果 x 和 y 的长度不相等
* @throws {Error} 如果 x 或 y 的长度小于 2
* @returns {number} 样本协方差
* @example
* sampleCovariance([1, 2, 3, 4, 5, 6], [6, 5, 4, 3, 2, 1]); // => -3.5
*/
function sampleCovariance(x, y) {
// 两个数据集的长度必须相等,且长度必须大于 1
if (x.length !== y.length) {
throw new Error("sampleCovariance 需要等长的样本数据");
}
if (x.length < 2) {
throw new Error("sampleCovariance 需要每个样本至少包含两个数据点");
}
// 计算每个数据集的均值,以便衡量每个值相对于均值的偏差。
// 这样,当一个数据集为 [1, 2, 3],另一个为 [2, 3, 4] 时,
// 它们的协方差不会因为绝对数值的不同而受到影响。
const xmean = mean(x);
const ymean = mean(y);
let sum = 0;
// 对于每一对数据点,当它们相对于各自均值的偏差方向一致时,
// 协方差增加——如果两者均高于均值或均低于均值,
// 则协方差会显著增加。
for (let i = 0; i < x.length; i++) {
sum += (x[i] - xmean) * (y[i] - ymean);
}
// 贝塞尔校正(Bessel's Correction):对样本统计量进行调整,
// 以补偿由于使用样本数据而导致的自由度减少。
const besselsCorrection = x.length - 1;
// 计算加权协方差,归一化处理数据集的长度。
return sum / besselsCorrection;
}
export default sampleCovariance;