Skip to content
Snippets Groups Projects
Commit 386828e1 authored by RABEHI AMIRA p2312013's avatar RABEHI AMIRA p2312013
Browse files
parents ac795f59 2e52f96a
No related branches found
No related tags found
No related merge requests found
......@@ -14,6 +14,6 @@ cols = ['Anis', 'Maya', 'Corentin', 'Amira']
data[cols] = data[cols].round(2)
# Exporter les données nettoyées au format JSON
data.to_json('sleep_combined_clean.json', orient='records', date_format='iso')
data.to_json('steps_combined_clean.json', orient='records', date_format='iso')
print("Le fichier 'steps_combined_clean.json' a été créé avec succès.")
d3.json("sleep_combined_clean.json").then(function(data) {
// Fonction pour filtrer les mois en fonction de l'année sélectionnée
function getMonthsForYear(year) {
return d3.timeMonths(new Date(year + "-01-01"), new Date(year + "-12-31"));
}
// Parsing des dates et tri des données par mois
data.forEach(d => {
d.date = d3.timeParse("%Y-%m-%d")(d.date);
d.month = d3.timeMonth(d.date);
});
// Création du groupe pour chaque membre
var members = ["Anis", "Maya", "Corentin", "Amira"];
// Fonction de mise à jour du graphique en fonction de l'année et des membres sélectionnés
function updateChart(selectedYear, selectedMembers) {
const monthsForYear = getMonthsForYear(selectedYear);
// Filtrage des données par mois
var groupedData = d3.group(data, d => d.month);
// Transformation des données en format plus approprié pour la visualisation
var nestedData = monthsForYear.map(month => {
const valuesForMonth = groupedData.get(month) || [];
const avgMonthSleep = selectedMembers.map(member => {
const memberData = valuesForMonth.filter(d => d[member] !== null);
return {
member: member,
value: memberData.length > 0 ? d3.mean(memberData, v => v[member]) : null // Utiliser null pour les données manquantes
};
});
return {
month: month,
values: avgMonthSleep
};
});
// Dimensions du graphique
var width = 800, height = 400;
var margin = { top: 20, right: 120, bottom: 60, left: 60 };
// Création des échelles
var x = d3.scaleBand()
.domain(monthsForYear)
.range([margin.left, width - margin.right])
.padding(0.05); // Réduire l'espacement entre les mois
var y = d3.scaleLinear()
.domain([0, d3.max(nestedData, d => d3.max(d.values, v => v.value))])
.nice()
.range([height - margin.bottom, margin.top]);
var color = d3.scaleOrdinal()
.domain(selectedMembers)
.range(["#ff6347", "#4682b4", "#32cd32", "#ff1493"]);
// Création du SVG
var svg = d3.select("#chart")
.attr("width", width)
.attr("height", height);
// Nettoyer le SVG avant de redessiner
svg.selectAll("*").remove();
// Ajouter les axes
svg.append("g")
.attr("transform", `translate(0, ${height - margin.bottom})`)
.call(d3.axisBottom(x)
.tickFormat(d3.timeFormat("%B")) // Utilisation du format du mois pour l'axe X
.ticks(d3.timeMonth.every(1)) // Affichage de chaque mois
)
.selectAll("text")
.style("text-anchor", "middle")
.style("font-size", "12px");
svg.append("g")
.attr("transform", `translate(${margin.left}, 0)`)
.call(d3.axisLeft(y));
// Ajouter les titres des axes
svg.append("text")
.attr("x", width / 2)
.attr("y", height - 5)
.attr("text-anchor", "middle")
.style("font-size", "16px")
.text("Mois");
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("x", -height / 2)
.attr("y", 20)
.attr("text-anchor", "middle")
.style("font-size", "16px")
.text("Heures de sommeil");
// Création du tooltip
var tooltip = d3.select("body").append("div")
.attr("class", "tooltip")
.style("position", "absolute")
.style("visibility", "hidden")
.style("background-color", "rgba(0, 0, 0, 0.7)")
.style("color", "white")
.style("padding", "5px")
.style("border-radius", "5px")
.style("pointer-events", "none");
// Dessiner les barres
svg.append("g")
.selectAll("g")
.data(nestedData)
.enter().append("g")
.attr("transform", d => `translate(${x(d.month)}, 0)`)
.selectAll("rect")
.data(d => d.values.filter(v => selectedMembers.includes(v.member) && v.value !== null)) // Filtrer les données null
.enter().append("rect")
.attr("x", (d, i) => i * (x.bandwidth() / selectedMembers.length)) // Coller les barres
.attr("y", d => y(d.value))
.attr("width", x.bandwidth() / selectedMembers.length - 1) // Ajuster la largeur des barres
.attr("height", d => height - margin.bottom - y(d.value))
.attr("fill", d => color(d.member))
.on("mouseover", function(event, d) {
tooltip.style("visibility", "visible")
.text(d.member + ": " + d.value.toFixed(2) + " heures");
})
.on("mousemove", function(event) {
tooltip.style("top", (event.pageY + 5) + "px")
.style("left", (event.pageX + 5) + "px");
})
.on("mouseout", function() {
tooltip.style("visibility", "hidden");
});
// Ajouter la légende
var legend = svg.append("g")
.attr("transform", `translate(${width - margin.right + 20}, ${margin.top})`);
selectedMembers.forEach((member, i) => {
var legendRow = legend.append("g")
.attr("transform", `translate(0, ${i * 20})`);
legendRow.append("rect")
.attr("width", 15)
.attr("height", 15)
.attr("fill", color(member));
legendRow.append("text")
.attr("x", 20)
.attr("y", 12)
.style("font-size", "12px")
.text(member);
});
}
// Initialisation avec tous les membres
updateChart(2024, ["Anis", "Maya", "Corentin", "Amira"]);
// Gestion des changements dans les sélections
d3.select("#yearSelect").on("change", function() {
const selectedYear = this.value;
const selectedMembers = Array.from(document.querySelectorAll("#memberSelect input:checked")).map(input => input.value);
updateChart(selectedYear, selectedMembers);
});
d3.select("#memberSelect").on("change", function() {
const selectedYear = d3.select("#yearSelect").node().value;
const selectedMembers = Array.from(document.querySelectorAll("#memberSelect input:checked")).map(input => input.value);
updateChart(selectedYear, selectedMembers);
});
});
......@@ -8,9 +8,7 @@
</head>
<body>
<div class="container">
<!-- Conteneur de la partie sélecteurs à gauche -->
<div class="selectors">
<!-- Sélecteur d'année sous forme de liste déroulante -->
<label for="yearSelect">Choisissez l'année:</label>
<select id="yearSelect">
<option value="2024">2024</option>
......@@ -18,8 +16,7 @@
<option value="2022">2022</option>
<option value="2021">2021</option>
</select>
<!-- Sélecteur de membres sous forme de cases à cocher -->
<label for="memberSelect">Choisissez des membres:</label>
<form id="memberSelect">
<input type="checkbox" id="Anis" value="Anis" checked> Anis<br>
......@@ -29,13 +26,13 @@
</form>
</div>
<!-- Espace pour le graphique -->
<svg id="chart">
<!-- Titre du graphique à placer dans le SVG -->
<text id="chartTitle" x="50%" y="30" text-anchor="middle" font-size="20" fill="#333">Comparaison des Cycles de Sommeil</text>
</svg>
</div>
<svg id="chart"></svg>
<button id="backButton">Retour</button>
<!-- Espace pour afficher les détails du mois sélectionné -->
<svg id="dailyChart" style="display: none;"></svg>
</div>
<div id="tooltip" style="position: absolute; background-color: rgba(0, 0, 0, 0.7); color: white; padding: 5px; border-radius: 4px; pointer-events: none; display: none;"></div>
<script src="https://d3js.org/d3.v7.min.js"></script>
<script src="script.js"></script>
</body>
......
d3.json("sleep_combined_clean.json").then(function(data) {
// Fonction pour filtrer les mois en fonction de l'année sélectionnée
function getMonthsForYear(year) {
return d3.timeMonths(new Date(year + "-01-01"), new Date(year + "-12-30"));
}
// Fonction pour filtrer les données par mois
data.forEach(d => {
d.date = d3.timeParse("%Y-%m-%d")(d.date);
d.month = d3.timeMonth(d.date);
});
// Fonction pour afficher les heures de sommeil des jours d'un mois
function showDayDetails(selectedYear, selectedMember, selectedMonth, memberColor) {
const monthData = data.filter(d => d.month.getMonth() === selectedMonth.getMonth() && d.date.getFullYear() === selectedYear && d[selectedMember] !== null);
// Créer une liste des 31 jours du mois
const daysInMonth = Array.from({ length: 30 }, (_, i) => i + 1); // jours de 1 à 31
const dailyData = daysInMonth.map(day => {
const dataForDay = monthData.find(d => d.date.getDate() === day);
return {
day: day, // Afficher uniquement le jour
sleepHours: dataForDay ? dataForDay[selectedMember] : null // Afficher uniquement les heures de sommeil
};
});
// Mise à jour du graphique des jours
const width = 800, height = 400;
const margin = { top: 20, right: 60, bottom: 60, left: 60 };
const x = d3.scaleBand()
.domain(dailyData.map(d => d.day)) // Utilisation de 'day' au lieu de la date complète
.range([margin.left, width - margin.right])
.padding(0.1);
const y = d3.scaleLinear()
.domain([0, d3.max(dailyData, d => d.sleepHours)])
.nice()
.range([height - margin.bottom, margin.top]);
const svg = d3.select("#dailyChart")
.attr("width", width)
.attr("height", height);
svg.selectAll("*").remove(); // Supprimer les anciens graphiques
// Ajouter un titre au-dessus du graphique
svg.append("text")
.attr("x", width / 2) // Centrer horizontalement
.attr("y", margin.top + 30) // Positionner légèrement au-dessus du graphique
.attr("text-anchor", "middle") // Centrer le texte
.style("font-size", "16px") // Taille de police
.style("font-weight", "bold") // Gras
.text("Analyse des heures de sommeil par jours");
// Ajouter un label à l'axe X
d3.select("#dailyChart").append("text")
.attr("transform", `translate(${width / 2}, ${height - margin.bottom + 50})`) // Positionner le label sous l'axe X
.style("text-anchor", "middle")
.style("font-size", "14px")
.text("Jour");
// Ajouter un label à l'axe Y
d3.select("#dailyChart").append("text")
.attr("transform", `rotate(-90)`)
.attr("y", margin.left - 40) // Positionner à gauche de l'axe Y
.attr("x", -height / 2) // Centrer le label verticalement par rapport à l'axe Y
.style("text-anchor", "middle")
.style("font-size", "14px")
.text("Heures de sommeil");
svg.append("g")
.attr("transform", `translate(0, ${height - margin.bottom})`)
.call(d3.axisBottom(x))
.selectAll("text")
.style("text-anchor", "middle")
.style("font-size", "12px");
svg.append("g")
.attr("transform", `translate(${margin.left}, 0)`)
.call(d3.axisLeft(y));
svg.append("g")
.selectAll("rect")
.data(dailyData)
.enter().append("rect")
.attr("x", d => x(d.day)) // Affichage selon les jours
.attr("y", d => y(d.sleepHours))
.attr("width", x.bandwidth())
.attr("height", d => height - margin.bottom - y(d.sleepHours))
.attr("fill", memberColor) // Utilisation de la couleur passée en paramètre
.on("mouseover", function(event, d) {
// Afficher le tooltip au survol de la souris
d3.select("#tooltip")
.style("display", "block")
.html(`${d.sleepHours.toFixed(2)}h`)
.style("left", (event.pageX + 5) + "px") // Positionnement du tooltip horizontalement
.style("top", (event.pageY - 28) + "px"); // Positionnement du tooltip verticalement
})
.on("mouseout", function() {
// Masquer le tooltip lorsqu'on sort de la barre
d3.select("#tooltip").style("display", "none");
});
// Afficher le graphique des jours
document.getElementById("dailyChart").style.display = "block";
// Masquer le graphique principal
document.getElementById("chart").style.display = "none";
// Afficher le bouton "Retour"
document.getElementById("backButton").style.display = "block";
}
// Fonction pour mettre à jour le graphique principal
function updateChart(selectedYear, selectedMembers) {
const monthsForYear = getMonthsForYear(selectedYear);
const groupedData = d3.group(data, d => d.month);
const nestedData = monthsForYear.map(month => {
const valuesForMonth = groupedData.get(month) || [];
const avgMonthSleep = selectedMembers.map(member => {
const memberData = valuesForMonth.filter(d => d[member] !== null);
return {
member: member,
value: memberData.length > 0 ? d3.mean(memberData, v => v[member]) : null
};
});
return {
month: month,
values: avgMonthSleep
};
});
var width = 800, height = 400;
var margin = { top: 20, right: 120, bottom: 60, left: 60 };
var x = d3.scaleBand()
.domain(monthsForYear)
.range([margin.left, width - margin.right])
.padding(0.05);
var y = d3.scaleLinear()
.domain([0, d3.max(nestedData, d => d3.max(d.values, v => v.value))])
.nice()
.range([height - margin.bottom, margin.top]);
var color = d3.scaleOrdinal()
.domain(selectedMembers)
.range(["#ff6347", "#4682b4", "#32cd32", "#ff1493"]);
var svg = d3.select("#chart")
.attr("width", width)
.attr("height", height);
svg.selectAll("*").remove();
svg.append("g")
.attr("transform", `translate(0, ${height - margin.bottom})`)
.call(d3.axisBottom(x)
.tickFormat(d3.timeFormat("%B"))
.ticks(d3.timeMonth.every(1))
)
.selectAll("text")
.style("text-anchor", "middle")
.style("font-size", "12px");
svg.append("g")
.attr("transform", `translate(${margin.left}, 0)`)
.call(d3.axisLeft(y));
// Ajouter un label à l'axe X
d3.select("#chart").append("text")
.attr("transform", `translate(${width / 2}, ${height - margin.bottom + 50})`) // Positionner le label sous l'axe X
.style("text-anchor", "middle")
.style("font-size", "14px")
.text("Mois");
// Ajouter un label à l'axe Y
d3.select("#chart").append("text")
.attr("transform", `rotate(-90)`)
.attr("y", margin.left - 40) // Positionner à gauche de l'axe Y
.attr("x", -height / 2) // Centrer le label verticalement par rapport à l'axe Y
.style("text-anchor", "middle")
.style("font-size", "14px")
.text("Heures de sommeil");
svg.append("g")
.selectAll("g")
.data(nestedData)
.enter().append("g")
.attr("transform", d => `translate(${x(d.month)}, 0)`)
.selectAll("rect")
.data(d => d.values.filter(v => selectedMembers.includes(v.member) && v.value !== null))
.enter().append("rect")
.attr("x", (d, i) => i * (x.bandwidth() / selectedMembers.length))
.attr("y", d => y(d.value))
.attr("width", x.bandwidth() / selectedMembers.length - 1)
.attr("height", d => height - margin.bottom - y(d.value))
.attr("fill", d => color(d.member))
.on("click", function(event, d) {
var selectedMonth = d3.timeMonth(d3.timeParse("%Y-%m-%d")(d.month));
var selectedMember = d.member;
var memberColor = color(selectedMember); // Récupère la couleur du membre
showDayDetails(selectedYear, selectedMember, selectedMonth, memberColor); // Passe la couleur au graphique quotidien
})
.on("mouseover", function(event, d) {
// Afficher le tooltip avec la moyenne des heures de sommeil pour le mois
d3.select("#tooltip")
.style("display", "block")
.html(` ${d3.timeFormat("%B")(d.month)}${d.value.toFixed(2)}h`)
.style("left", (event.pageX + 5) + "px") // Positionnement horizontal du tooltip
.style("top", (event.pageY - 28) + "px"); // Positionnement vertical du tooltip
})
.on("mouseout", function() {
// Masquer le tooltip lorsqu'on sort de la barre
d3.select("#tooltip").style("display", "none")});
// Ajouter une légende
var legend = svg.append("g")
.attr("transform", `translate(${width - margin.right + 20}, ${margin.top})`);
//ajouter un titre au chart
svg.append("text")
.attr("x", width / 2) // Centrer horizontalement
.attr("y", margin.top + 10) // Positionner légèrement au-dessus du graphique
.attr("text-anchor", "middle") // Centrer le texte
.style("font-size", "16px") // Taille de police
.style("font-weight", "bold") // Gras
.text("Analyse des heures de sommeil par mois");
selectedMembers.forEach((member, i) => {
var legendRow = legend.append("g")
.attr("transform", `translate(0, ${i * 20})`);
legendRow.append("rect")
.attr("width", 15)
.attr("height", 15)
.attr("fill", color(member));
legendRow.append("text")
.attr("x", 20)
.attr("y", 12)
.style("font-size", "12px")
.text(member);
});
}
// Écouteur pour le bouton "Retour"
document.getElementById("backButton").addEventListener("click", function() {
// Masquer le graphique des jours
document.getElementById("dailyChart").style.display = "none";
// Réafficher le graphique principal
document.getElementById("chart").style.display = "block";
// Masquer le bouton "Retour"
document.getElementById("backButton").style.display = "none";
});
// Initialisation avec tous les membres
updateChart(2024, ["Anis", "Maya", "Corentin", "Amira"]);
// Écouteur d'événement pour les changements d'année et de membres
document.getElementById("yearSelect").addEventListener("change", function() {
var selectedYear = this.value;
var selectedMembers = Array.from(document.querySelectorAll("#memberSelect input:checked"))
.map(checkbox => checkbox.value);
updateChart(selectedYear, selectedMembers);
});
document.querySelectorAll("#memberSelect input").forEach(input => {
input.addEventListener("change", function() {
var selectedYear = document.getElementById("yearSelect").value;
var selectedMembers = Array.from(document.querySelectorAll("#memberSelect input:checked"))
.map(checkbox => checkbox.value);
updateChart(selectedYear, selectedMembers);
});
});
});
This diff is collapsed.
......@@ -72,3 +72,35 @@ select {
pointer-events: none;
font-size: 14px;
}
#dailyChart {
display: none; /* Masquer par défaut */
width: 800px;
height: 400px;
background-color: #ffffff;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
margin-top: 20px;
}
button {
background-color: #4682b4;
color: white;
border: none;
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
border-radius: 5px;
transition: background-color 0.3s;
position: fixed;
top: 20px;
right: 20px;
display: none; /* Hidden by default */
}
button:hover {
background-color: #365f8c;
}
#backButton {
z-index: 10;
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment