计算与前一个元素和一个新元素的标准差 (σ) (cumulative/incremental SD)
Calculate standard deviation (σ) from the previous one and a new element (cumulative/incremental SD)
正在对 运行 流程进行基准测试,其中计算了以下数字 "cumulatively"(根据以前的值 + 新元素):
- 最短持续时间
- 最长持续时间
- 平均时长
Standard Deviation (σ) of the duration is supposed to be calculated as well, because it indicates the statistical dispersion.
基于应用,不方便逐个存储element/number,所以需要结合之前的值和新的元素进行计算
示例:
NewElement Min Max Avg StdDev // AllElements (which are NOT meant to be stored)
1 1 1 1 - [1]
2 1 2 1.5 0.5 [1,2]
3 1 3 2 0.8164965809277 [1,2,3]
4 1 4 2.5 1.1180339887499 [1,2,3,4]
0 0 4 2 1.4142135623731 [1,2,3,4,0]
(而this是SD的在线计算器,供参考)
目标的简化版本是:
const calculateNewStats = (stats, newElement) => {
const newStats = {};
newStats.count = stats.count + 1;
newStats.min = Math.min(stats.min, newElement);
newStats.max = Math.max(stats.max, newElement);
newStats.avg = (stats.avg * stats.count + newElement) / newStats.count;
// newStats.sd = ??? that's the problem
return newStats;
};
// initial values
let stats = {
count: 0,
min: 0,
max: 0,
avg: 0,
// initial SD is theoretically controversial (N/A), but that's not the point
sd: 0,
};
// loopStart goes here ... an infinite one
// many things goes here ... eventually, we have a `newElement`
stats = calculateNewStats(stats, newElement);
// loopEnd goes here
搜索了一段时间,找到了一些数学方程式(如this)并仔细应用,但结果数字不正确。
the page you linked 上的算法确实有效,这是一个有效的实现:
const calculateNewStats = (stats, newElement) => {
const newStats = {};
newStats.count = stats.count + 1;
newStats.min = Math.min(stats.min, newElement);
newStats.max = Math.max(stats.max, newElement);
newStats.avg = (stats.avg * stats.count + newElement) / newStats.count;
newStats.sd = Math.sqrt(
(
(newStats.count - 1) * stats.sd * stats.sd +
(newElement - newStats.avg) * (newElement - stats.avg)
) / (newStats.count)
);
return newStats;
};
// initial values
let stats = {
count: 0,
min: 0,
max: 0,
avg: 0,
sd: 0
};
let newElements = [1, 2, 3, 4, 0];
for (let newElement of newElements) {
stats = calculateNewStats(stats, newElement);
console.log(stats);
}
也许你错过了最后一句话?
If you want the population variance or standard deviation replace N-1 with N and N-2 with N-1.
注意:精度会略有下降,随着元素的添加,精度会越来越大。我建议:
- 将方差与
sd
一起存储在stats
中;现在我正在计算方差的平方根以获得 SD,然后对 SD 求平方以获得下一次迭代的方差
- 将总值存储在
stats
中,而不是在每次迭代时用 stats.avg * stats.count
重新计算它
您在 stats
中存储了 2 个以上的数字,但您的数字应该会更精确。
这是一个更好的实现:
const calculateNewStats = (stats, newElement) => {
const newStats = {};
newStats.count = stats.count + 1;
newStats.total = stats.total + newElement;
newStats.min = Math.min(stats.min, newElement);
newStats.max = Math.max(stats.max, newElement);
newStats.avg = (stats.total + newElement) / newStats.count;
newStats.variance = (
(newStats.count - 1) * stats.variance +
(newElement - newStats.avg) * (newElement - stats.avg)
) / (newStats.count);
newStats.sd = Math.sqrt(newStats.variance);
return newStats;
};
// initial values
let stats = {
count: 0,
total: 0,
min: 0,
max: 0,
avg: 0,
sd: 0,
variance: 0
};
let newElements = [1, 2, 3, 4, 0];
for (let newElement of newElements) {
stats = calculateNewStats(stats, newElement);
console.log(stats);
}
正在对 运行 流程进行基准测试,其中计算了以下数字 "cumulatively"(根据以前的值 + 新元素):
- 最短持续时间
- 最长持续时间
- 平均时长
Standard Deviation (σ) of the duration is supposed to be calculated as well, because it indicates the statistical dispersion.
基于应用,不方便逐个存储element/number,所以需要结合之前的值和新的元素进行计算
示例:
NewElement Min Max Avg StdDev // AllElements (which are NOT meant to be stored)
1 1 1 1 - [1]
2 1 2 1.5 0.5 [1,2]
3 1 3 2 0.8164965809277 [1,2,3]
4 1 4 2.5 1.1180339887499 [1,2,3,4]
0 0 4 2 1.4142135623731 [1,2,3,4,0]
(而this是SD的在线计算器,供参考)
目标的简化版本是:
const calculateNewStats = (stats, newElement) => {
const newStats = {};
newStats.count = stats.count + 1;
newStats.min = Math.min(stats.min, newElement);
newStats.max = Math.max(stats.max, newElement);
newStats.avg = (stats.avg * stats.count + newElement) / newStats.count;
// newStats.sd = ??? that's the problem
return newStats;
};
// initial values
let stats = {
count: 0,
min: 0,
max: 0,
avg: 0,
// initial SD is theoretically controversial (N/A), but that's not the point
sd: 0,
};
// loopStart goes here ... an infinite one
// many things goes here ... eventually, we have a `newElement`
stats = calculateNewStats(stats, newElement);
// loopEnd goes here
搜索了一段时间,找到了一些数学方程式(如this)并仔细应用,但结果数字不正确。
the page you linked 上的算法确实有效,这是一个有效的实现:
const calculateNewStats = (stats, newElement) => {
const newStats = {};
newStats.count = stats.count + 1;
newStats.min = Math.min(stats.min, newElement);
newStats.max = Math.max(stats.max, newElement);
newStats.avg = (stats.avg * stats.count + newElement) / newStats.count;
newStats.sd = Math.sqrt(
(
(newStats.count - 1) * stats.sd * stats.sd +
(newElement - newStats.avg) * (newElement - stats.avg)
) / (newStats.count)
);
return newStats;
};
// initial values
let stats = {
count: 0,
min: 0,
max: 0,
avg: 0,
sd: 0
};
let newElements = [1, 2, 3, 4, 0];
for (let newElement of newElements) {
stats = calculateNewStats(stats, newElement);
console.log(stats);
}
也许你错过了最后一句话?
If you want the population variance or standard deviation replace N-1 with N and N-2 with N-1.
注意:精度会略有下降,随着元素的添加,精度会越来越大。我建议:
- 将方差与
sd
一起存储在stats
中;现在我正在计算方差的平方根以获得 SD,然后对 SD 求平方以获得下一次迭代的方差 - 将总值存储在
stats
中,而不是在每次迭代时用stats.avg * stats.count
重新计算它
您在 stats
中存储了 2 个以上的数字,但您的数字应该会更精确。
这是一个更好的实现:
const calculateNewStats = (stats, newElement) => {
const newStats = {};
newStats.count = stats.count + 1;
newStats.total = stats.total + newElement;
newStats.min = Math.min(stats.min, newElement);
newStats.max = Math.max(stats.max, newElement);
newStats.avg = (stats.total + newElement) / newStats.count;
newStats.variance = (
(newStats.count - 1) * stats.variance +
(newElement - newStats.avg) * (newElement - stats.avg)
) / (newStats.count);
newStats.sd = Math.sqrt(newStats.variance);
return newStats;
};
// initial values
let stats = {
count: 0,
total: 0,
min: 0,
max: 0,
avg: 0,
sd: 0,
variance: 0
};
let newElements = [1, 2, 3, 4, 0];
for (let newElement of newElements) {
stats = calculateNewStats(stats, newElement);
console.log(stats);
}