Public
Edited
May 5
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
workbook = FileAttachment("JOLTS.xlsx").xlsx()
Insert cell
workbook.sheetNames
Insert cell
function parseMonYY(dateStr) {
const months = {
Jan: 1, Feb: 2, Mar: 3, Apr: 4, May: 5, Jun: 6,
Jul: 7, Aug: 8, Sep: 9, Oct: 10, Nov: 11, Dec: 12
};
const [mon, yy] = dateStr.split('-');
const year = 2000 + parseInt(yy);
return new Date(year, months[mon], 1);
}
Insert cell
data = workbook.sheet(0, {
headers: true,
parse: {
Date: d => parseMonYY(d) // Use our custom parser
}
})
Insert cell
data
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
viewof chart1 = {
const filtered = data.filter(d =>
d["Rate Type"] === rateFilter &&
d.Area === areaFilter
);

return Plot.plot({
height: 400,
marginLeft: 60,
marks: [
Plot.line(filtered, {
x: "Date",
y: "Rate",
stroke: "Area",
strokeWidth: 2
}),
Plot.ruleY([0]),
Plot.tip(filtered, Plot.pointer({
x: "Date",
y: "Rate",
stroke: "Area",
title: d => `${d.Area} - ${d.Date}\nJob Openings Rate: ${d.Rate}%`
}))
],
x: {
type: "band",
label: "Date"
},
y: {
label: "Job Openings Rate (%)",
grid: true
},
title: `rate type Over Time `
});
}
Insert cell
viewof chart2 = {
const filtered = data.filter(d =>
["Hiring Rate", "Quit Rate", "Layoff Rate"].includes(d["Rate Type"]) &&
d.Area === areaFilter
);

return Plot.plot({
height: 500,
marginLeft: 80,
marks: [
Plot.barY(filtered, {
x: "Rate Type",
y: "Rate",
fill: "Area",
fx: "Date",
sort: {fx: "x", reduce: "median", reverse: true},
tip: true
}),
Plot.ruleY([0])
],
x: {
label: "Rate Type"
},
y: {
label: "Rate (%)",
grid: true
},
facet: {
data: filtered,
x: "Date",
marginRight: 120
},
title: `Comparison of Labor Metrics of area`
});
}
Insert cell
viewof chart3 = {
const filtered = data.filter(d => d["Rate Type"] === "Job opening rate"&&
d.Area === areaFilter );
return Plot.plot({
height: 400,
marginLeft: 60,
marks: [
Plot.dot(filtered, {
x: "Job openings",
y: "Hires",
fill: "Area",
r: 4,
tip: true
}),
Plot.linearRegressionY(filtered, {
x: "Job openings",
y: "Hires",
stroke: "Area"
})
],
x: {
label: "Job Openings (thousands)",
grid: true
},
y: {
label: "Hires (thousands)",
grid: true
},
title: "Correlation Between Job Openings and Hires"
});
}
Insert cell
viewof rateFilter = Inputs.select(
["Job opening rate", "Layoff Rate", "Quit Rate", "Hiring Rate"],
{label: "Rate type", value: "Job opening rate"}
);
Insert cell

// Interaction 2: Filter by area
viewof areaFilter = Inputs.select(
["United States", "North Carolina"],
{label: "Area", value: "United States"}
);
Insert cell

## Insights & Design Decisions
<li>The dashboard separates national vs regional insights using an area filter to help localize decisions.</li>
<li>Date range filtering enables better focus on trends across recession and recovery periods.</li>
<li>KPI cards summarize key rates for quick understanding of current conditions.</li>
<li>Charts are linked through filters for consistent comparative analysis.</li>
<li>Interactive tooltips enable exploration without overwhelming visual clutter.</li>

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