Graphe pyramide des ages

This commit is contained in:
2025-10-17 20:44:32 +02:00
parent 0d1ebd1020
commit 43ded8e883
5 changed files with 74 additions and 55 deletions

View File

@@ -5,7 +5,24 @@
<title>Distribution des âges</title> <title>Distribution des âges</title>
</head> </head>
<body style="max-width: 700px; margin: 2rem auto; font-family: sans-serif;"> <body style="max-width: 700px; margin: 2rem auto; font-family: sans-serif;">
<h3>Distribution des âges selon le genre</h3> <h2>Distribution des âges</h2>
<section id="stats" style="margin-bottom: 2rem;">
<h3>Indicateurs clés</h3>
<table>
<tr>
<td class="strong">Individus</td><td id="total" class="number"></td>
<td class="strong">Âge moyen</td><td id="mean" class="number"></td>
</tr>
<tr>
<td class="strong">Médiane</td><td id="median" class="number"></td>
<td class="strong">Écart-type</td><td id="ecart" class="number"></td>
</tr>
<tr>
<td class="strong">Minimum</td><td id="min" class="number"></td>
<td class="strong">Maximum</td><td id="max" class="number"></td>
</tr>
</table>
</section>
<canvas id="ageChart" width="600" height="400"></canvas> <canvas id="ageChart" width="600" height="400"></canvas>
<script type="module" src="/src/individus.ts"></script> <script type="module" src="/src/individus.ts"></script>
</body> </body>

View File

@@ -1,5 +1,9 @@
import { jStat } from "jstat"; import { jStat } from "jstat";
/**
* @param tableau
* @returns un élémént pris au hasard dans le tableau
*/
function randomChoice(ens:Array<any>) { function randomChoice(ens:Array<any>) {
return ens[Math.floor(Math.random() * ens.length)]; return ens[Math.floor(Math.random() * ens.length)];
} }
@@ -9,17 +13,18 @@ function choiceAge() {
if (r < 0.35) { if (r < 0.35) {
const age = jStat.normal.sample(25, 4); const age = jStat.normal.sample(25, 4);
return Math.min(30, Math.max(18, Math.round(age))); return Math.min(40, Math.max(18, Math.round(age)));
} }
if (r < 0.75) { if (r < 0.75) {
const age = jStat.normal.sample(40, 6); const age = jStat.normal.sample(46, 6);
return Math.min(60, Math.max(31, Math.round(age))); return Math.min(60, Math.max(31, Math.round(age)));
} }
const age = jStat.normal.sample(66, 5); const age = jStat.normal.sample(62, 5);
return Math.min(78, Math.max(61, Math.round(age))); return Math.min(78, Math.max(55, Math.round(age)));
} }
function randomFirstName(sex:string, age:number) { function randomFirstName(sex:string, age:number) {
const pool = [ const pool = [
[ [
@@ -27,10 +32,11 @@ function randomFirstName(sex:string, age:number) {
"Tom","Medhi","Evan","Sacha","Rayan","Mathis","Enzo","Théo","Isaac","Liam" "Tom","Medhi","Evan","Sacha","Rayan","Mathis","Enzo","Théo","Isaac","Liam"
], ],
[ "Julien","Maxime","Alexandre","Pierre","Antoine","Romain","Jérémy","Kevin","Nicolas","Benjamin", [ "Julien","Maxime","Alexandre","Pierre","Antoine","Romain","Jérémy","Kevin","Nicolas","Benjamin",
"Florian","Vincent","Michaël","Samuel","Baptiste","Yann","Cédric","Quentin","Thomas","Adrien" "Florian","Vincent","Michaël","Samuel","Baptiste","Yann","Cédric","Quentin","Thomas","Adrien",
"Emmanuel", "Marc", "Sébastien", "Olivier", "Laurent"
], ],
[ "Jean","Michel","Christian","Philippe","Daniel","Patrick","Bernard","Alain","Jacques","Guy", [ "Jean","Michel","Christian","Philippe","Daniel","Patrick","Bernard","Alain","Jacques","Guy",
"Louis","André","Roger","Maurice","Robert","Henri","Marc","Gérard","Serge","Raymond" "Louis","André","Roger","Maurice","Robert","Henri","François","Gérard","Serge","Raymond", "Didier"
] ]
], ],
[ [
@@ -38,7 +44,8 @@ function randomFirstName(sex:string, age:number) {
"Camille","Nina","Darya","Léna","Louise","Inès","Julia","Samia","Clara","Maya" "Camille","Nina","Darya","Léna","Louise","Inès","Julia","Samia","Clara","Maya"
], ],
[ "Marine","Laura","Céline","Charlotte","Elodie","Marion","Sophie","Julie","Amélie","Amandine", [ "Marine","Laura","Céline","Charlotte","Elodie","Marion","Sophie","Julie","Amélie","Amandine",
"Valérie","Aurélie","Isabelle","Caroline","Sonia","Laurence","Cécile","Stéphanie","Sandrine","Emilie" "Valérie","Aurélie","Isabelle","Caroline","Sonia","Laurence","Cécile","Stéphanie","Sandrine","Emilie",
"Hélène", "Myriam", "Murielle"
], ],
[ "Marie","Monique","Françoise","Denise","Nicole","Pierrette","Madeleine","Colette","Agnès","Simone", [ "Marie","Monique","Françoise","Denise","Nicole","Pierrette","Madeleine","Colette","Agnès","Simone",
"Geneviève","Jacqueline","Jeanne","Yvonne","Raymonde","Thérèse","Lucienne","Gisèle","Marguerite","Suzanne" "Geneviève","Jacqueline","Jeanne","Yvonne","Raymonde","Thérèse","Lucienne","Gisèle","Marguerite","Suzanne"
@@ -46,14 +53,16 @@ function randomFirstName(sex:string, age:number) {
] ]
]; ];
let a = 2; const ageGroups = [
{ max: 30, index: 0 },
{ max: 50, index: 1 },
{ max: Infinity, index: 2 }
];
if (age <= 30) const p = ageGroups.find(g => age <= g.max)?.index ?? 2;
a = 0; const s = sex === 'M' ? 0 : 1;
else if (age <= 50)
a = 1;
return randomChoice(pool[sex == 'M' ? 0 : 1][a]); return randomChoice(pool[s][p]);
} }
function randomSex(age:number) { function randomSex(age:number) {

View File

@@ -1,16 +1,33 @@
// src/main.ts import './style.css';
import { generate } from "./individual"; import { generate } from "./individual";
import Chart from "chart.js/auto"; import Chart from "chart.js/auto";
import { jStat } from "jstat";
const individus = generate(1000); const individus = generate(1000);
console.log(individus);
function formatStats(ages: number[]) {
return {
"total": ages.length,
"mean": jStat.mean(ages).toFixed(1),
"median": jStat.median(ages).toFixed(1),
"ecart": jStat.stdev(ages).toFixed(1),
"min": Math.min(...ages),
"max": Math.max(...ages)
};
}
const Ages:number[] = individus.map(i => i.age);
// Séparer les âges par sexe // Séparer les âges par sexe
const agesH = individus.filter(i => i.sexe === "M").map(i => i.age); const AgesH = individus.filter(i => i.sexe === "M").map(i => i.age);
const agesF = individus.filter(i => i.sexe === "F").map(i => i.age); const AgesF = individus.filter(i => i.sexe === "F").map(i => i.age);
const stats = formatStats(Ages);
for (const [key, value] of Object.entries(stats)) {
document.getElementById(key)!.innerText = value.toString();
}
// Construire des classes d'âge // Construire des classes d'âge
const ageClasses = Array.from({ length: 13 }, (_, i) => i * 5 + 18); // [10,20,30,...,70] const ageClasses = Array.from({ length: 20 }, (_, i) => i * 3 + 18);
function histogramData(ages: number[]) { function histogramData(ages: number[]) {
return ageClasses.map((a, idx) => return ageClasses.map((a, idx) =>
@@ -23,16 +40,16 @@ const ctx = document.getElementById("ageChart") as HTMLCanvasElement;
new Chart(ctx, { new Chart(ctx, {
type: "bar", type: "bar",
data: { data: {
labels: ageClasses.map(a => `${a}-${a+9}`), labels: ageClasses.map(a => `${a}-${a+2}`),
datasets: [ datasets: [
{ {
label: "Hommes", label: "Hommes",
data: histogramData(agesH), data: histogramData(AgesH),
backgroundColor: "rgba(54, 162, 235, 0.6)", backgroundColor: "rgba(54, 162, 235, 0.6)",
}, },
{ {
label: "Femmes", label: "Femmes",
data: histogramData(agesF), data: histogramData(AgesF),
backgroundColor: "rgba(255, 99, 132, 0.6)", backgroundColor: "rgba(255, 99, 132, 0.6)",
} }
], ],

View File

@@ -1,4 +1,4 @@
import './style.css' import './style.css';
import Graph from "graphology"; import Graph from "graphology";
import Sigma from "sigma"; import Sigma from "sigma";
import forceAtlas2 from "graphology-layout-forceatlas2"; import forceAtlas2 from "graphology-layout-forceatlas2";

View File

@@ -13,6 +13,14 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.strong {
font-weight: 700;
}
.number {
text-align: right;
}
a { a {
font-weight: 500; font-weight: 500;
color: #646cff; color: #646cff;
@@ -22,18 +30,6 @@ a:hover {
color: #535bf2; color: #535bf2;
} }
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
#app { #app {
width: 100vw; width: 100vw;
@@ -41,26 +37,6 @@ h1 {
background: white background: white
} }
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vanilla:hover {
filter: drop-shadow(0 0 2em #3178c6aa);
}
.card {
padding: 2em;
}
.read-the-docs {
color: #888;
}
button { button {
border-radius: 8px; border-radius: 8px;