Public
Edited
Mar 3
Importers
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
csvURL = "https://docs.google.com/spreadsheets/d/e/2PACX-1vRB0YYEeJqFIAgHqzqUgPEo6KDuSas3x_NdSA6HLCRSSOlhXiG7Hldh_R9Bhq4vsw/pub?gid=33282564&single=true&output=csv"
Insert cell
rawData = d3.csv(csvURL)
Insert cell
data = rawData.map(item => {
return {
...item,
partic_rech_flujo: parseFloat(item.partic_rech_flujo),
año: parseInt(item.año),
mes: parseInt(item.mes),
eventos_de_entrada: parseInt(item.eventos_de_entrada),
rechazados: parseInt(item.rechazados),
total_de_eventos: parseInt(item.total_de_eventos),
porcentaje_rechazo: parseFloat(item.porcentaje_rechazo.replaceAll(",", "."))
};
});
Insert cell
datasets = [
{name: "Rechazados", variable: "rechazados", format: "s"},
{name: "Eventos de entrada", variable: "eventos_de_entrada", format: "s"},
{name: "Porcentaje de rechazo", variable: "porcentaje_rechazo", format: "p"},
]
Insert cell
filteredCountry = data.filter(item => regionSelection.includes(item.region));
Insert cell
yearsInterval = Array.from({length: yearsSelection[1] - yearsSelection[0] + 1}, (_, i) => yearsSelection[0] + i)
Insert cell
yearGrouped = Array.from(
d3.rollup(
data,
v => ({
rechazados: d3.sum(v, d => d.rechazados),
eventos_de_entrada: d3.sum(v, d => d.eventos_de_entrada),
total_de_eventos: d3.sum(v, d => d.eventos_de_entrada) + d3.sum(v, d => d.rechazados),
porcentaje_rechazo: (d3.sum(v, d => d.rechazados) / (d3.sum(v, d => d.eventos_de_entrada) + d3.sum(v, d => d.rechazados))),
region: v[0].region
}),
d => d.pais, // First level of grouping by 'pais'
d => d.año // Second level of grouping by 'año'
)
).flatMap(([pais, countryValues]) =>
Array.from(countryValues, ([año, { rechazados, eventos_de_entrada, total_de_eventos, porcentaje_rechazo, region }]) => ({
pais: pais,
año: año,
rechazados: rechazados,
eventos_de_entrada: eventos_de_entrada,
total_de_eventos: total_de_eventos,
porcentaje_rechazo: porcentaje_rechazo,
region: region
}))
).sort((a, b) => b.año - a.año)
Insert cell
filteredData = yearGrouped.filter(item => countrySelection.includes(item.pais));
Insert cell
regionYearGrouped = Array.from(
d3.rollup(
yearGrouped,
v => ({
rechazados: d3.sum(v, d => d.rechazados), // Summing 'rechazados'
eventos_de_entrada: d3.sum(v, d => d.eventos_de_entrada), // Keeping 'eventos_de_entrada'
total_de_eventos: d3.sum(v, d => d.eventos_de_entrada) + d3.sum(v, d => d.rechazados), // Summing 'eventos_de_entrada' and 'rechazados'
porcentaje_rechazo: (d3.sum(v, d => d.rechazados) / (d3.sum(v, d => d.eventos_de_entrada) + d3.sum(v, d => d.rechazados)))
}),
d => d.region, // First level of grouping by 'region'
d => d.año // Second level of grouping by 'año'
)
).flatMap(([region, countryValues]) =>
Array.from(countryValues, ([año, { rechazados, eventos_de_entrada, total_de_eventos, porcentaje_rechazo }]) => ({
region: region,
año: año,
rechazados: rechazados,
eventos_de_entrada: eventos_de_entrada,
total_de_eventos: total_de_eventos,
porcentaje_rechazo: porcentaje_rechazo
}))
).sort((a, b) => b.año - a.año)
Insert cell
filteredTableData = yearSelection.sort((a, b) => b.porcentaje_rechazo - a.porcentaje_rechazo)
.filter(item => regionTableSelection.includes(item.region))
Insert cell
countryData = data.filter(item => country.includes(item.pais))
Insert cell
Insert cell
plotLineFunc = (año, color) => {
return Plot.lineY(
data.filter(item => item.año === año && item.pais == countryLine),
{
x: "mes",
y:varMesesSelection[0].variable,
stroke: color,
// tip: true
}
)
};
Insert cell
plotDotFunc = (año, color) => {
return Plot.dot(
data.filter(item => item.año === año && item.pais == countryLine),
{
x: "mes",
y: varMesesSelection[0].variable,
fill: color,
// tip: true
}
)
}
Insert cell
textMarkFunc = (año, color) => {
return Plot.text(
data.filter(item => item.año === año && item.pais == countryLine),
Plot.selectMaxY({
x: "mes",
y: varMesesSelection[0].variable,
text: d => d.año,
dy: -10,
fill: color,
stroke: "white",
strokeWidth: 5,
})
)
}
Insert cell
function assignColors(yearsInterval) {
// Find the maximum, second last and minimum values
let sortedYears = [...yearsInterval].sort((a, b) => a - b);
let maxYear = sortedYears[sortedYears.length - 1];
let secondLastYear = sortedYears[sortedYears.length - 2];
let minYear = sortedYears[0];

let result = [];
let functions = [plotLineFunc, plotDotFunc, textMarkFunc];

for (let func of functions) {
for (let i = 0; i < yearsInterval.length; i++) {
let color;
if (yearsInterval[i] === maxYear) {
color = "#ff0000"; // Color for the maximum value
} else if (yearsInterval[i] === secondLastYear) {
color = "#000000"; // Color for the second last value
} else {
// Calculate a gradient of gray colors for the rest of the values
// The closer the year is to the minimum year, the lighter the gray color
// Subtract a constant (e.g., 50) to ensure the minimum color value is not #FFFFFF
let grayScale = Math.floor(205 - 205 * ((yearsInterval[i] - minYear) / (maxYear - minYear))).toString(16);
color = `#${grayScale}${grayScale}${grayScale}`;
}

// Call the function and store the result
result.push(func(yearsInterval[i], color));
}
}

return result;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more