prev_comb = await FileAttachment('dados/dados1/previsoes_combinad.csv').csv()
prev_lm = await FileAttachment('dados/dados2/previoes_lm.csv').csv()
prev_lc = await FileAttachment('dados/dados2/previoes_lc.csv').csv()
modelos = ["ARIMA+ETS", "Lee-Carter", "Lee-Miller"]
regioes = ["Brasil", "Centro-Oeste", "Nordeste", "Norte", "Sudeste", "Sul", "Acre", "Alagoas", "Amapá", "Amazonas", "Bahia", "Ceará", "Distrito Federal", "Espírito Santo", "Goiás", "Maranhão", "Mato Grosso", "Mato Grosso do Sul", "Minas Gerais", "Pará", "Paraíba", "Paraná", "Pernambuco", "Piauí", "Rio de Janeiro", "Rio Grande do Norte", "Rio Grande do Sul", "Rondônia", "Roraima", "Santa Catarina", "São Paulo", "Sergipe", "Tocantins"]
// Definição do componente reativo
// Define o componente de seleção
viewof seletores2 = {
const form = html`<form style="
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 30px;
justify-content: center;
">
<!-- Select para Região -->
<div style="min-width: 200px; max-width: 300px;">
<label style="display: block; text-align: center; margin-bottom: 8px;">Local:</label>
<select name="regiao" style="
display: block;
margin: 0 auto;
padding: 6px 12px;
border: 1px solid #ccc;
border-radius: 20px;
font-size: 16px;
text-align: center;
width: fit-content;
min-width: 180px;
background-color: #f8f9fa;
">
${regioes.map(r => `<option value="${r}">${r}</option>`).join('')}
</select>
</div>
<!-- Checkboxes para Modelos -->
<div style="min-width: 200px; max-width: 300px;">
<label style="display: block; text-align: center; margin-bottom: 8px;">Modelo:</label>
<select name="modelo" style="
display: block;
margin: 0 auto;
padding: 6px 12px;
border: 1px solid #ccc;
border-radius: 20px;
font-size: 16px;
text-align: center;
width: fit-content;
min-width: 180px;
background-color: #f8f9fa;
">
${modelos.map(r => `<option value="${r}">${r}</option>`).join('')}
</select>
</div>
<!-- Radio para Sexo -->
<div style="min-width: 200px; max-width: 300px;">
<label style="display: block; text-align: center; margin-bottom: 8px;">Sexo:</label>
<div style="
display: flex;
gap: 15px;
justify-content: center;
">
<label style="display: flex; align-items: center; gap: 5px;">
<input type="radio" name="sexo" value="Ambos" checked>
Ambos
</label>
<label style="display: flex; align-items: center; gap: 5px;">
<input type="radio" name="sexo" value="Homens">
Homens
</label>
<label style="display: flex; align-items: center; gap: 5px;">
<input type="radio" name="sexo" value="Mulheres">
Mulheres
</label>
</div>
</div>
</form>`;
// Definir valor inicial
form.value = {
regiao: regioes[5],
modelo: 'ARIMA+ETS',
sexo: 'Ambos'
};
// Atualizar valor ao modificar select
form.querySelector('select[name="regiao"]').addEventListener('change', e => {
form.value = {
...form.value,
regiao: e.target.value
};
form.dispatchEvent(new Event('input'));
});
// Atualizar valor ao modificar checkboxes
form.querySelector('select[name="modelo"]').addEventListener('change', e => {
form.value = {
...form.value,
modelo: e.target.value
};
form.dispatchEvent(new Event('input'));
});
// Atualizar valor ao modificar radios
const radios = form.querySelectorAll('input[name="sexo"]');
for (const radio of radios) {
radio.addEventListener('change', () => {
form.value = {
...form.value,
sexo: radio.value
};
form.dispatchEvent(new Event('input'));
});
}
return form;
}
// Extrair valores individuais em células separadas
regiao2 = seletores2.regiao
modelo2 = seletores2.modelo
sexo = seletores2.sexo
data_filter1 = prev_comb.filter(d => d.Local === regiao2 && d.Sexo === sexo).map(d => ({
ano: +d.Ano,
faixa: d.faixa_etaria,
prev: Math.log(d.nMx_previsão)
}))
data_filter2 = prev_lm.filter(d => d.regiao === regiao2 && d.taxa === sexo).map(d => ({
ano: +d.ano,
faixa: d.Faixa_Etaria,
prev: Math.log(d.previsto)
}))
data_filter3 = prev_lc.filter(d => d.regiao === regiao2 && d.taxa === sexo).map(d => ({
ano: +d.ano,
faixa: d.Faixa_Etaria,
prev: Math.log(d.previsto)
}))
// Função principal para criar gráficos
function createChart(data, title) {
const ptBRLocaleDefinition = {
decimal: ",",
thousands: "",
grouping: [3],
currency: ["R$", ""]
};
d3.formatDefaultLocale(ptBRLocaleDefinition);
const width = 760;
const height = 500;
const margin = {top: 30, right: 20, bottom: 40, left: 50};
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height])
.attr("width", width)
.attr("height", height)
.attr("style", "max-width: 100%; height: auto; height: intrinsic; font: 10px sans-serif;")
.style("-webkit-tap-highlight-color", "transparent")
.style("overflow", "visible");
// Escalas
const x = d3.scalePoint()
.domain([...new Set(data.map(d => d.faixa))])
.range([margin.left, width - margin.right])
.padding(0.5);
const y = d3.scaleLinear()
.domain(d3.extent(data, d => d.prev)).nice()
.range([height - margin.bottom, margin.top]);
// Eixos
svg.append("g")
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x))
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", "rotate(-45)");
svg.append("text")
.attr("text-anchor", "middle")
.attr("x", width / 2)
.attr("y", height) // Posição abaixo do eixo
.style("font-size", "14px")
.style("fill", "currentColor")
.text("Faixa Etária");
svg.append("g")
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(y).ticks(height / 40))
.call(g => g.select(".domain").remove())
.style("font-size", "12px")
.call(g => g.selectAll(".tick line").clone()
.attr("x2", width - margin.left - margin.right)
.attr("stroke-opacity", 0.1))
.call(g => g.append("text")
.attr("x", -margin.left)
.attr("y", 15)
.attr("fill", "currentColor")
.attr("text-anchor", "start")
.style("font-size", "18px")
.text("log(Mx)"));
// Gradiente e cores
const colorScale = d3.scaleSequential(d3.interpolateViridis)
.domain([2024, 2070]);
const defs = svg.append("defs");
const nestedData = d3.groups(data, d => d.ano);
nestedData.forEach(([year, values]) => {
const gradientId = `gradient-${title}-${year}`;
const gradient = defs.append("linearGradient")
.attr("id", gradientId)
.attr("gradientUnits", "userSpaceOnUse")
.attr("x1", margin.left)
.attr("y1", 0)
.attr("x2", width - margin.right)
.attr("y2", 0);
gradient.append("stop")
.attr("offset", "0%")
.attr("stop-color", colorScale(year));
gradient.append("stop")
.attr("offset", "100%")
.attr("stop-color", colorScale(Math.min(year + 10, 2070)));
});
// Linhas
const line = d3.line()
.x(d => x(d.faixa))
.y(d => y(d.prev));
nestedData.forEach(([year, values]) => {
svg.append("path")
.datum(values)
.attr("fill", "none")
.attr("stroke", `url(#gradient-${title}-${year})`)
.attr("stroke-width", 2.5)
.attr("d", line);
});
// Legenda
const legendWidth = 200;
const legendHeight = 20;
const legendX = width - margin.right - legendWidth;
const legendY = margin.top;
const legendGradient = defs.append("linearGradient")
.attr("id", `legend-${title}`)
.attr("x1", "0%")
.attr("y1", "0%")
.attr("x2", "100%")
.attr("y2", "0%");
const years = [2024, 2035, 2045, 2055, 2070];
years.forEach((year, i) => {
legendGradient.append("stop")
.attr("offset", `${i * 100 / (years.length - 1)}%`)
.attr("stop-color", colorScale(year));
});
svg.append("rect")
.attr("x", legendX)
.attr("y", legendY)
.attr("width", legendWidth)
.attr("height", legendHeight)
.style("fill", `url(#legend-${title})`);
svg.append("text")
.attr("x", legendX)
.attr("y", legendY - 5)
.attr("font-size", "12px")
.text("Anos (2024-2070)");
years.forEach((year, i) => {
svg.append("text")
.attr("x", legendX + (i * legendWidth / (years.length - 1)))
.attr("y", legendY + legendHeight + 15)
.attr("text-anchor", "middle")
.attr("font-size", "10px")
.text(year);
});
// Título
svg.append("text")
.attr("x", width / 2)
.attr("y", 20)
.attr("text-anchor", "middle")
.style("font-size", "1.2em")
.text(title);
return svg.node();
}
// Renderização dos gráficos
{
const container = document.createElement('div');
container.style.display = "grid";
container.style.gap = "2rem";
container.style.justifyContent = "center";
if (modelo2.includes("ARIMA+ETS")) {
container.appendChild(createChart(data_filter1, "ARIMA+ETS"));
}
if (modelo2.includes("Lee-Miller")) {
container.appendChild(createChart(data_filter2, "Lee-Miller"));
}
if (modelo2.includes("Lee-Carter")) {
container.appendChild(createChart(data_filter3, "Lee-Carter"));
}
return modelo2.length === 0
? html`<p>Nenhum dado selecionado.</p>`
: container;
}