standard deviation for comparison table
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 55s

This commit is contained in:
Tudor Sitaru
2026-01-06 15:49:57 +00:00
parent 1e3fd5f8cc
commit d891b1d46c

View File

@@ -468,7 +468,6 @@ async function updateComparisonChart() {
} }
function updateComparisonTable(comparison, metric, years) { function updateComparisonTable(comparison, metric, years) {
const firstYear = years[0];
const lastYear = years[years.length - 1]; const lastYear = years[years.length - 1];
const prevYear = years.length > 1 ? years[years.length - 2] : null; const prevYear = years.length > 1 ? years[years.length - 2] : null;
@@ -477,11 +476,11 @@ function updateComparisonTable(comparison, metric, years) {
years.forEach(year => { years.forEach(year => {
headerHtml += `<th>${year}</th>`; headerHtml += `<th>${year}</th>`;
}); });
if (prevYear && prevYear !== firstYear) { if (prevYear) {
headerHtml += `<th title="Change from ${prevYear} to ${lastYear}">Δ 1yr</th>`; headerHtml += `<th title="Change from ${prevYear} to ${lastYear}">Δ 1yr</th>`;
} }
if (years.length > 1) { if (years.length > 2) {
headerHtml += `<th title="Change from ${firstYear} to ${lastYear}">Δ ${firstYear}${lastYear}</th>`; headerHtml += `<th title="Standard deviation of scores (lower = more consistent)">Variability</th>`;
} }
elements.tableHeader.innerHTML = headerHtml; elements.tableHeader.innerHTML = headerHtml;
@@ -496,7 +495,6 @@ function updateComparisonTable(comparison, metric, years) {
yearlyMap[d.year] = d[metric]; yearlyMap[d.year] = d[metric];
}); });
const firstValue = yearlyMap[firstYear];
const lastValue = yearlyMap[lastYear]; const lastValue = yearlyMap[lastYear];
const prevValue = prevYear ? yearlyMap[prevYear] : null; const prevValue = prevYear ? yearlyMap[prevYear] : null;
@@ -505,10 +503,16 @@ function updateComparisonTable(comparison, metric, years) {
const oneYearChangeStr = oneYearChange !== null ? oneYearChange.toFixed(1) : 'N/A'; const oneYearChangeStr = oneYearChange !== null ? oneYearChange.toFixed(1) : 'N/A';
const oneYearClass = oneYearChange !== null ? (oneYearChange >= 0 ? 'positive' : 'negative') : ''; const oneYearClass = oneYearChange !== null ? (oneYearChange >= 0 ? 'positive' : 'negative') : '';
// Calculate total change // Calculate variability (standard deviation) - exclude null/0 values
const totalChange = firstValue != null && lastValue != null ? (lastValue - firstValue) : null; const values = years.map(y => yearlyMap[y]).filter(v => v != null && v !== 0);
const totalChangeStr = totalChange !== null ? totalChange.toFixed(1) : 'N/A'; let variabilityStr = 'N/A';
const totalChangeClass = totalChange !== null ? (totalChange >= 0 ? 'positive' : 'negative') : ''; if (values.length >= 2) {
const mean = values.reduce((a, b) => a + b, 0) / values.length;
const squaredDiffs = values.map(v => Math.pow(v - mean, 2));
const variance = squaredDiffs.reduce((a, b) => a + b, 0) / values.length;
const stdDev = Math.sqrt(variance);
variabilityStr = '±' + stdDev.toFixed(1);
}
const color = CHART_COLORS[index % CHART_COLORS.length]; const color = CHART_COLORS[index % CHART_COLORS.length];
@@ -518,11 +522,11 @@ function updateComparisonTable(comparison, metric, years) {
const value = yearlyMap[year]; const value = yearlyMap[year];
bodyHtml += `<td>${value != null ? formatMetricValue(value, metric) : '-'}</td>`; bodyHtml += `<td>${value != null ? formatMetricValue(value, metric) : '-'}</td>`;
}); });
if (prevYear && prevYear !== firstYear) { if (prevYear) {
bodyHtml += `<td class="${oneYearClass}">${oneYearChangeStr !== 'N/A' ? (oneYearChange >= 0 ? '+' : '') + oneYearChangeStr : oneYearChangeStr}</td>`; bodyHtml += `<td class="${oneYearClass}">${oneYearChangeStr !== 'N/A' ? (oneYearChange >= 0 ? '+' : '') + oneYearChangeStr : oneYearChangeStr}</td>`;
} }
if (years.length > 1) { if (years.length > 2) {
bodyHtml += `<td class="${totalChangeClass}">${totalChangeStr !== 'N/A' ? (totalChange >= 0 ? '+' : '') + totalChangeStr : totalChangeStr}</td>`; bodyHtml += `<td>${variabilityStr}</td>`;
} }
bodyHtml += `</tr>`; bodyHtml += `</tr>`;
}); });