Public
Edited
Apr 3, 2024
4 stars
Insert cell
Insert cell
Insert cell
// dashboard = html`
// <style>
// body{color: black;}
// .dash_div {
// margin: 0 auto;
// background-color: #fffcf7;
// border : 3px solid 3px;
// border-radius : 10px;
// padding: 5px;
// font-family: Inter;
// }

// .dash_div h1 { font-size: 16px; text-align: center; margin:2% 0 0 0; }
// .dash_div h2 { font-size: 14px; text-align: center; margin:2% 0 0 0; }
// .dash_div h3 { font-size: 12px; margin:2% 0 0 0; }
// .dash_div h4 { font-size: 10px; text-align: center; margin:1% 0 0 0; }
// .dash_div h5 { font-size: 9px; text-align: center; margin:2% 0 0 0; }
// .dash_div p {
// font-size: 8px;
// text-align: center;
// padding:1%
// }

// .dash_div table{
// font-size: 7px;
// text-align:center;
// border-collapse: collapse;
// }
// .dash_div td, th{
// font-size: 14px;
// width: 100px;
// border: 1px solid white;
// text-align: center;
// }
// #table_seas table{
// border-collapse: separate;
// border-spacing : 10px 5px;
// border-bottom: 1px solid gray;

// }
// #showmore{
// width:100%;
// margin:auto;
// }
// #showmore button{
// background-color: #f5f5f5;
// border: 1px solid #b1b8cc;
// border-radius: 5px;
// padding:5px;
// margin:0px auto;
// }
// </style>


// <div class="dash_div">
// <table>
// <tr>
// <td colspan="3" style="padding:0px; margin:0px">
// ${cp_chart(hierarchy2bis, { width: 900, height: 800 })}
// <span style="background-color: white; font-size: 15px; font-weight: bold; padding: .8em 2em; margin: 1em 0em;">
// Aliments les plus riches en &nbsp;&nbsp; ${viewof nutr_selection}
// </span>
// </td>
// </tr>
// <tr>
// <td>
// ${bar_chart(packed_circle_select, { width: 600, height: 400 })}
// ${viewof nutrients_cbx}
// </td>
// <td>
// <h3></h3>
// <span>${get_saison_meteorologique(
// Math.round(season + 1)
// )} ${viewof season}</span>
// <span id="table_seas">${table_seas(
// headers_sais,
// data_sais,
// showmore
// )}</span>
// <span id="showmore">${viewof showmore}</span>
// </td>
// </tr>
// </table>
// </div>
// `
Insert cell
Insert cell
Insert cell
mutable bar_food = []
Insert cell
Insert cell
stacked_bar_chart(packed_circle_select, { width: 800, height: 500 })
Insert cell
function stacked_bar_chart(
dataset,
{
space = 200,
width = 500 + space,
height = 500 + space / 2,
stroke = "white",
padding = 3,
margin = { top: 20, right: 30, bottom: 30, left: 40 },
vb_pad = 10,
fill = "white",
fillOpacity = 0.9,
strokeWidth,
strokeOpacity
} = {}
) {
// A: Initialization
if (dataset.length <= 1) return;
const nutrientKeys = Object.keys(dataset[0].nutriments);

// B: Data Preparation
let stackedData = dataset.map((item) => {
let flattened = { name: item.name };
nutrientKeys.forEach((key) => {
flattened[key] = item.nutriments[key];
});
return flattened;
});
let series = d3.stack().keys(nutrientKeys)(stackedData);

console.log("Data set", dataset);
console.log("Keys for stacking", nutrientKeys);
console.log("Stacked Data", stackedData);
console.log(
"Stacked Data Entries",
stackedData.map((d) => Object.entries(d))
);
console.log("Series after stacking", series);

// C: Scales and Colors
// total_fat, saturated_fat, sugars, fiber, carbohydrate, protein, calcium
const colors = [
"#F9C80E",
"#F1A60F",
"#EAF2EF",
"#046865",
"#D3F8E2",
"#9E2A2B",
"#E9F1F7"
];
const c = d3.scaleOrdinal().domain(nutrientKeys).range(colors);

// D: SVG Creation
const svg = d3.create("svg").attr("width", width).attr("height", height);

// E: Axes Configuration
const x = d3
.scaleBand()
.domain(nutrientKeys)
.rangeRound([margin.left, width - margin.right])
.padding(0.1);

const yMax = d3.max(series, (layer) =>
d3.max(layer, (segment) => segment[1])
);
const y = d3
.scaleLinear()
.domain([0, yMax])
.range([height - margin.bottom, margin.top]);

// F: Drawing Bars
svg
.append("g")
.selectAll("g")
.data(series)
.enter()
.append("g")
.attr("fill", (d, i) => c(d.key))
.selectAll("rect")
.data((d) => d)
.enter()
.append("rect")
.attr("x", (d, i) => console.log(d))
.attr("y", (d) => y(d[1]))
.attr("height", (d) => y(d[0]) - y(d[1]))
.attr("width", x.bandwidth())
.attr("stroke", "black")
.append("title")
.text((d) => "min: " + d[0] + "max: " + d[1]);

// G: Axes Addition
let xAxis = (g) =>
g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x));
let yAxis = (g) =>
g.attr("transform", `translate(${margin.left},0)`).call(d3.axisLeft(y));
svg.append("g").call(xAxis);
svg.append("g").call(yAxis);

return svg.node();
}
Insert cell
Insert cell
packed_circle_select
Insert cell
packed_circle_select.length > 0
? packed_circle_select.length >= 1
? stacked_bar_chart(packed_circle_select, { width: 600, height: 500 })
: bar_chart(packed_circle_select[0], { width: 600, height: 500 })
: bar_chart(null_select, { width: 600, height: 500 })
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function bar_chart(
dataset,
{
space = 200,
width = 500 + space,
height = 500 + space / 2,
stroke = "white",
padding = 3,
margin = { top: 20, right: 30, bottom: 30, left: 40 },
vb_pad = 10,
fill = "white",
fillOpacity = 0.9,
strokeWidth,
strokeOpacity
} = {}
) {
// A: Initialization

let nom = dataset.name;
let data = filter_cb(dataset);
let nutriments = dataset.nutriments;
let calories = nutriments.calories;
delete nutriments.calories;

// B: Data Preparation
data = Object.entries(data);

// C: Scales and Colors
// total_fat, saturated_fat, sugars, fiber, carbohydrate, protein, calcium
const colors = [
"#F9C80E",
"#F1A60F",
"#EAF2EF",
"#046865",
"#D3F8E2",
"#9E2A2B",
"#E9F1F7"
];
const c = d3.scaleOrdinal().domain(nutriments_selection).range(colors);

// D: SVG Creation
const svg = d3.create("svg").attr("width", width).attr("height", height);

// E: Axes Configuration
const x = d3
.scaleBand()
.domain(d3.map(data, (d) => d[0]))
.range([margin.left, width - margin.right]);
const y = d3
.scaleLinear()
.domain([d3.max(data, (d) => d[1]), 0])
.range([margin.top, height - margin.bottom]);

// F: Drawing Bars
svg
.append("g")
.attr("transform", `translate(${margin.left}, 0)`)
.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("x", (d, i) => i * x.bandwidth())
.attr("y", (d, i) => y(d[1]))
.attr("width", x.bandwidth())
.attr("height", (d, i) => height - y(d[1]) - margin.bottom)
.attr("fill", (d) => c(d))
.attr("stroke", "black")
.append("title")
.text((d) => d[1] + " g");

// G: Axes Addition
let xAxis = (g) =>
g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x));
let yAxis = (g) =>
g.attr("transform", `translate(${margin.left},0)`).call(d3.axisLeft(y));
svg.append("g").call(xAxis);
svg.append("g").call(yAxis);

return svg.node();
}
Insert cell
# Circle Pack Chart
Insert cell
Insert cell
mutable packed_circle_select = []
Insert cell
function cp_chart(
data,
{
children,
space = 300,
width = 500 + space,
height = 500 + space / 2,
fill = "white",
fillOpacity = 0.9,
stroke = "white",
padding = 3,
vb_pad = 30,
strokeWidth,
strokeOpacity,
pad = { top: 20, bottom: 50, left: 15, right: 20 }
} = {}
) {
if (!(data instanceof d3.hierarchy)) throw "Data is not a d3.hierarchy";

const W = width - width / 10;
const H = height - height / 10;
const color = d3
.scaleOrdinal()
.domain(Array.from(groupes))
.range(d3.schemeTableau10);

// Layout.
function pack_data2() {
return d3.pack().size([W, H]).padding(padding)(
// inter-cercles
data
);
}
const packed = pack_data2();
// Compute labels and titles.
const descendants = packed.descendants();
const feuilles = packed.leaves();
feuilles.forEach((d, i) => (d.index = i));
let title = (d) =>
d.height == 0
? `${d.parent.data[0]}\n${[...d.data[0].split(",")]}\n`
: `${d.data[0]}\n`;
// SVG
const svg = d3
.create("svg")
.attr("viewBox", [-5, -5, width, height])
.attr("font-size", 13)
.attr("font-family", "sans-serif")
.style("fill", "none")
.style("stroke-width", ".03px");

// groupe pour chaque element ~~~
const leaf = svg
.selectAll("g")
.data(descendants)
.enter()
.append("g")
.attr("transform", (d) => `translate(${d.x},${d.y})`)
.attr("class", (d) => d.data[0]);

const circle = leaf
.append("circle")
.attr("r", (d) => d.r)
.attr("fill", (d) => (d.children ? (d.height == 1 ? null : "black") : fill))
.attr("fill-opacity", (d) => (d.children ? null : fillOpacity))
.attr("stroke", (d) => (d.height == 1 ? color(d.data[0]) : null))
.attr("stroke-width", (d) =>
d.height == 1 ? `${d3.max([4, padding - 3])}px` : null
)
.on("click", handleClick)
.on("mouseover", (e, d) => {
handleMouseOverCircle(e, d, svg, width, height, vb_pad, color);
})
.on("mouseout", (e, d) => {
if (d.depth <= 1) handleMouseOutCircle(svg);
})
// title
.append("title")
.text((d) => (d.height < 2 ? title(d) : null));

initClef(svg, vb_pad, color);

return svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function selected_dr(node, parent = null) {
if (parent == null || !node.data || node.data.length === 0) return;

let arr = bar_food;
mutable bar_food.length = 0;

let submap = bd2_rollup.get(parent.data[0]);
if (!submap) return;
let food = submap.get(node.data[0]);
if (!food) return;
let map_iterator_food = food.keys();

let mapIter = map_iterator_food[Symbol.iterator]();
let food_nutriments = mapIter.next().value;
if (!food_nutriments) return;
let fnobj = {
name: node.data[0],
nutriments: Object.fromEntries(food_nutriments)
};
// Check if the object already exists in the 'packed_circle_select' array
let index = packed_circle_select.findIndex(
(item) => item.name === fnobj.name
);
if (index > -1) {
// If found, remove the object from the array
mutable packed_circle_select.splice(index, 1);
} else {
// If not found, add the new object to the array
mutable packed_circle_select.push(fnobj);
}

// bar_food = arr //need to check if exist
}
Insert cell
Insert cell
Insert cell
Insert cell
hierarchy2bis = d3.hierarchy(dataroll2_sel)
.sum(([,value]) => value)
.sort((a, b) => b.value - a.value)
Insert cell
nuno = hierarchy2.children[0].children[206]
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
table_seas(headers_sais, data_sais, showmore.value)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
de_saison = season_food.filter(food =>{
let seasel = Math.round(season)
return food.months.includes(seasel)
})
Insert cell
# Apport Quotidiens de Référence
### vidal
La recherche d'un jeu de données permettant la mise en place directe de cet élément de référence se trouve sans fruit, il nous faudra donc procéder par une approche littéraire en premier lieu.
Il faudra se méfier à tout prix d'erreurs de mésinformation.
> *"Il apparait indispensable de conserver la notion de « repères » et non de « recommandations », pour une meilleure compréhension et appropriation potentielles, et afin d’éviter qu’elles n’apparaissent comme des injonctions moralisatrices ou normatives. **L’approche est donc de formuler des conseils, des « repères » vers lesquels
tendre et non des normes à atteindre absolument, par tous."***
Source: [Repères du futur Programme national nutrition santé 2017-2021, HCSP](https://www.hcsp.fr/Explore.cgi/Telecharger?NomFichier=hcspa20170216_reperesalimentairesactua2017.pdf)
Insert cell
Insert cell
vidal_includes('Viande')
Insert cell
vidal_includes = (string) => {
return vidal.filter(obj => {
if(Object.entries(obj)[0][1].includes(string)) return obj
})
}
Insert cell
vidal = vidal_db_parsed.map(d => {
let z = {}
for(let prop in d){
(z[prop] = d[prop].trim())
}
return z
})
Insert cell
vidal_db_parsed =psv.parse(vidal_db)
Insert cell
psv = d3.dsvFormat(";")
Insert cell
vidal_db = FileAttachment("tb_vidal_AQR-2@1.txt").text()
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
rollup_fn = (base, str) =>
d3.rollup(base,
d => d,
d => d.name.toLowerCase().includes(str.toLowerCase())
)
Insert cell
food_h_adapt2 = {
let n_bd = food_h_parsed
let n_obj = new Object()
let t_obj = new Object()

for(let group in aqr_gObj){
aqr_gObj[group].map(fs => {
if(fs != ""){
let roll = rollup_fn(n_bd, fs)
if(n_obj.hasOwnProperty(group))
n_obj[group].concat(roll.get(true))
else
n_obj[group] = roll.get(true)
for(let food of n_obj[group]) {
food.group = group
}
n_bd = roll.get(false)
}
})
}
return [n_bd, n_obj]
}
Insert cell
food_h_adapt2[1]
Insert cell
Ici vient le temps de commencer à penser à notre hiérarchie, le processus à été contre intuitif car jusqu'ici la tache impliquait les groupements de donnes, or nous avons simplement a aplatir cette structure, après avoir ajouté l'attribut *group* à chaque entrée;
Insert cell
bd_adapt2 = {
let n_bd = []
let o_bd = food_h_adapt2[1]
Object.entries(o_bd).forEach(x => n_bd.push(x[1]))
return n_bd.flat()
}
Insert cell
### Group & Rollup
Et grâce à ce dernier objet,
Insert cell
bd2_group = d3.group(bd_adapt2, d => d.group, d => d.name)
Insert cell
bd2_rollup = d3.rollup(bd_adapt2,
v => {
let map = new Map()
let apport_total = 0
for(let nutr of cols_det.main) {
map.set(nutr, v[0][nutr])
if(nutr != 'calories' && nutr != "saturated_fat")
apport_total += v[0][nutr]
}
return new Map().set(map, apport_total.toFixed(2))
},
d => d.group,
d => d.name)
Insert cell
dataroll2_sel = bd2_rollup_sel(nutr_selection)
Insert cell
dataroll2_sel2 = {
let map = dataroll2_sel
map.delete("Conserve")
map.delete("Fast food")
return map
}
Insert cell
hierarchy2 = d3.hierarchy(bd2_rollup)
.sum(([,value]) => value)
.sort((a, b) => b.value - a.value)
Insert cell
bd2_rollup_sel = (nutr) => {
return d3.rollup(bd_adapt2,
v => +v[0][nutr].toFixed(2),
d => d.group,
d => d.name)
}
Insert cell
# Maquettage
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