Public
Edited
May 8
Insert cell
Insert cell
// 1) Imports
import {Plot} from "@observablehq/plot"


Insert cell

import {select, checkbox} from "@observablehq/inputs"

Insert cell
fitnessData = FileAttachment("FitnessTrackerDataset.csv").csv({typed:true})

Insert cell
// 3) Derive a Goal category for chart 2
categorized = fitnessData.map(d => ({
...d,
Goal: d.Workout_Type === "Cardio" || d.Workout_Type === "HIIT"
? "Weight Loss/Endurance"
: "Strength/Flexibility"
}))

Insert cell
avgByTypeExp = Object.values(
fitnessData.reduce((map, d) => {
// key on both type & experience
const key = `${d.Workout_Type}│${d.Experience_Level}`;
if (!map[key]) {
map[key] = {
Workout_Type: d.Workout_Type,
Experience_Level: d.Experience_Level,
sum: 0,
count: 0
};
}
map[key].sum += d.Calories_Burned;
map[key].count += 1;
return map;
}, {})
).map(d => ({
Workout_Type: d.Workout_Type,
Experience_Level: d.Experience_Level,
AvgCalories: d.sum / d.count
}));


Insert cell


// 3) Sort so the bars always appear in a consistent order
avgByTypeExp.sort((a, b) =>
d3.ascending(a.Workout_Type, b.Workout_Type) ||
d3.ascending(a.Experience_Level, b.Experience_Level)
);


Insert cell
// 3) Plot grouped bars + labels from our small avgByTypeExp array
chart1 = Plot.plot({
height: 400,
marginBottom: 60,

x: {
// Automatically picks up all workout types in avgByTypeExp
tickRotate: -30,
label: "Workout Type"
},
y: {
label: "Avg Calories Burned"
},
color: {
legend: true,
label: "Experience Level"
},

marks: [
// side‐by‐side bars by z: group
Plot.barY(avgByTypeExp, {
x: "Workout_Type",
z: "Experience_Level",
y: "AvgCalories",
fill: "Experience_Level"
}),

// text labels on top of each small bar
Plot.text(avgByTypeExp, {
x: "Workout_Type",
z: "Experience_Level",
y: "AvgCalories",
text: d => d.AvgCalories.toFixed(0),
dy: -6,
fill: "black"
})
]
})

Insert cell
import {slider} from "@observablehq/inputs"
Insert cell

category = fitnessData.map(d => ({
...d,
Goal: d.Workout_Type === "Cardio" || d.Workout_Type === "HIIT"
? "Weight Loss/Endurance"
: "Strength/Flexibility"
}))

Insert cell
Plot.plot({
marks: [
Plot.areaY(aapl, {x: "Workout_Type", y: "AvgCalories"}),
Plot.ruleY([0])
]
})
Insert cell
Plot.plot({
marks: [
Plot.areaY(aapl, {x: "Date", y: "Close"}),
Plot.ruleY([0])
]
})
Insert cell
Plot.plot({
marks: [
Plot.barY(alphabet, {x: "Workout_Type", y: "Cardio", sort: {x: "y", reverse: true}}),
Plot.ruleY([0])
]
})
Insert cell
Plot.plot({
marks: [
Plot.barX(alphabet, {x: "Workout_Type", y: "AvgCalories", sort: {y: "x", reverse: true}}),
Plot.ruleX([0])
]
})
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