Public
Edited
Jul 15, 2024
12 stars
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
data = d3
.rollups(
t1_resultats.filter((d) =>
["NFP", "ENS", "RN"].includes(groupes[d.CodNuaCand])
),
// .filter(
// (d) =>
// !t1_resultats
// .filter((d2) => d2.CodCirc2 == d.CodCirc2)
// .some((d2) => d2.Elu == "OUI")
// )
(d) => ({
c:
d3.greatest(
d.filter((d2) => groupes[d2.CodNuaCand] == "NFP"),
(d2) => d2.NbVoix
) || 0,
b:
d3.greatest(
d.filter((d2) => groupes[d2.CodNuaCand] == "ENS"),
(d2) => d2.NbVoix
) || 0,
a:
d3.greatest(
d.filter((d2) => groupes[d2.CodNuaCand] == "RN"),
(d2) => d2.NbVoix
) || 0,
candidats: d,
top_t1: groupes[d3.greatest(d, (d2) => d2.NbVoix).CodNuaCand] || "Autres",
top_t2: !t1_resultats
.filter((d2) => d2.CodCirc2 == d[0].CodCirc2)
.some((c) => c.Elu == "OUI")
? groupes[
d3.greatest(
t2_resultats.filter((d2) => d2.CodCirc2 == d[0].CodCirc2),
(d2) => d2.NbVoix
).CodNuaCand
] || "Autres"
: null,
exprimes: d3.sum(d, (d) => d.NbVoix),
desistement: desistements.find((d2) => d2[0] == d[0].CodCirc2)
}),
(d) => d.CodCirc2
)
.filter((d) => d[1].candidats.length == 3) // on garde seulement les circonscriptions comportant les 3 groupes
Insert cell
data2 = d3
.merge(
data.map((d) => {
const t1 = { ...d[1], CodCirc2: d[0], tour: 1 };
const t2 = d[1].top_t2 ? { ...d[1], CodCirc2: d[0], tour: 2 } : undefined;

return [t1, t2];
})
)
.filter((d) => d)
Insert cell
Insert cell
desistements = d3
.rollups(
t1_resultats.filter((d) => d.Elu == "QUALIF T2"),
(d) =>
d.filter(
(d2) =>
!t2_resultats.find(
(d3) =>
d2.NumPanneauCand == d3.NumPanneauCand &&
d2.CodCirc2 == d3.CodCirc2
)
),
(d) => d.CodCirc2
)
.filter((d) => d[1].length > 0)
Insert cell
t1_resultats = fetch_results(2024, 1)
Insert cell
t2_resultats = fetch_results(2024, 2)
Insert cell
Insert cell
triangulaires = d3
.rollups(
t1_resultats,
(D) => D.filter((d) => d.Elu == "QUALIF T2"),
(d) => d.CodCirc2
)
.filter((d) => d[1].length > 2)
Insert cell
Insert cell
plot_compare = (resultats) =>
Plot.plot({
...plot_options,
width,
height: 400,
projection: { type: ternary.projection, inset: 20, angle: 0 },
color: {
domain: Object.keys(couleurs_mdpt),
range: Object.values(couleurs_mdpt),
legend: true,
symbol: "circle"
},
r: {
zero: true
//domain: [0, d3.max(t1, (d) => d[1].exprimes)]
},
marks: [
Plot.sphere(),
ternary.graticule(),
ternary.tickLabels(),
ternary.labels(["RN", "ENS", "NFP"]),
Plot.dot(
resultats,
ternary.normalize({
a: (d) => d.a.NbVoix,
b: (d) => d.b.NbVoix,
c: (d) => d.c.NbVoix,
fill: (d) => (d.tour == 1 ? d.top_t1 : d.top_t2),
fx: (d) =>
d.tour == 1 ? "en tête au premier tour" : "en tête au second tour",
opacity: 0.8,
stroke: (d) => "white",
strokeWidth: 1,
//r: (d) => d[1].exprimes,
href: (d) =>
`https://elections.gouv.lol/legislatives/circonscription#${d.CodCirc2}`,
target: "_blank",
tip: true,
title: formatTip2
})
)
]
})
Insert cell
formatTip(data[42])
Insert cell
formatTip = (d) => {
return `${d[0]}
${d[1].a.NomPsn} : ${d[1].a.NbVoix.toLocaleString("fr")} voix
${d[1].b.NomPsn} : ${d[1].b.NbVoix.toLocaleString("fr")} voix
${d[1].c.NomPsn} : ${d[1].c.NbVoix.toLocaleString("fr")} voix`;
}
Insert cell
formatTip2 = (d) => {
return `${d.CodCirc2}
${d.a.NomPsn} : ${d.a.NbVoix.toLocaleString("fr")} voix
${d.b.NomPsn} : ${d.b.NbVoix.toLocaleString("fr")} voix
${d.c.NomPsn} : ${d.c.NbVoix.toLocaleString("fr")} voix`;
}
Insert cell
plot_wl(
data2.filter((d) =>
desistements
.filter((d) => d[1].map((d2) => groupes[d2.CodNuaCand]).includes("NFP"))
.map((d) => d[0])
.includes(d.CodCirc2)
)
)
Insert cell
winloss = (resultats) => {
const wl = [];
d3.rollups(
resultats,
(D) => ({
t1: D.find((d) => d.tour == 1),
t2: D.find((d) => d.tour == 2)
}),
(d) => d.CodCirc2
).forEach((d) => {
if (d[1].t1.top_t1 != d[1].t2.top_t2) {
return [
wl.push({ type: "loss", groupe: d[1].t1.top_t1 }),
wl.push({ type: "win", groupe: d[1].t2.top_t2 })
];
} else {
wl.push({ type: "keep", groupe: d[1].t1.top_t1 });
}
});

return wl; //, circonscriptions;
}
Insert cell
plot_wl = (desistements) =>
Plot.plot({
width,
color: {
domain: ["loss", "keep", "win"],
range: ["red", "black", "yellow"]
},
marks: [
Plot.dotY(
winloss(desistements),
Plot.stackY2({
y: (d) => (d.type == "loss" ? -1 : 1),
fill: "type",
sort: "type",
x: "groupe"
})
)
]
})
Insert cell
import { ternary } from "@fil/ternary-plot"
Insert cell
import {
groupes,
couleurs_mdpt,
fetch_results,
plot_options
} from "@taniki/lg2024-common"
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more