Acting Appointees Tracker
Explore data on presidential use of acting appointees and vacancies across federal departments and agencies
Under construction. This dashboard is a design preview populated with simulated placeholder data; it does not show real records. The actual dataset will replace it when it is ready for public release. Watch this space.
html`<div class="stat-grid">
<div class="stat-box">
<div class="stat-number">${totalPositions}</div>
<div class="stat-label">Total Positions Tracked</div>
</div>
<div class="stat-box stat-terracotta">
<div class="stat-number">${actingCount}</div>
<div class="stat-label">Filled by Actings</div>
</div>
<div class="stat-box stat-rose">
<div class="stat-number">${vacantCount}</div>
<div class="stat-label">Left Vacant</div>
</div>
<div class="stat-box">
<div class="stat-number">${avgDays}</div>
<div class="stat-label">Avg. Days as Acting</div>
</div>
</div>`// Aggregate data for stacked bar by department
deptStatusData = {
const depts = [...new Set(filtered.map(d => d.department))];
const statuses = ["Acting", "Confirmed", "Vacant"];
const result = [];
for (const dept of depts) {
for (const status of statuses) {
const count = filtered.filter(d => d.department === dept && d.status === status).length;
if (count > 0) {
result.push({ department: dept, status, count });
}
}
}
return result;
}// Aggregate data for timeline by quarter
timelineData = {
const result = [];
const quarters = {};
for (const d of filtered) {
const date = new Date(d.start_date);
const q = Math.floor(date.getMonth() / 3) + 1;
const key = `${date.getFullYear()}-Q${q}`;
if (!quarters[key]) {
quarters[key] = { quarter: key, date: new Date(date.getFullYear(), (q - 1) * 3, 1), Acting: 0, Vacant: 0 };
}
if (d.status === "Acting") quarters[key].Acting++;
else if (d.status === "Vacant") quarters[key].Vacant++;
}
for (const key of Object.keys(quarters).sort()) {
result.push({ date: quarters[key].date, count: quarters[key].Acting, series: "Acting" });
result.push({ date: quarters[key].date, count: quarters[key].Vacant, series: "Vacant" });
}
return result;
}Position Status by Department
Plot.plot({
marginLeft: 160,
marginRight: 20,
height: Math.max(300, deptStatusData.length * 8),
x: { label: "Count" },
y: { label: null },
color: {
domain: ["Acting", "Confirmed", "Vacant"],
range: ["#C06840", "#6B8F6B", "#B85C5C"],
legend: true
},
marks: [
Plot.barX(deptStatusData, {
y: "department",
x: "count",
fill: "status",
sort: { y: "-x" }
}),
Plot.ruleX([0])
]
})Acting Appointees Over Time
Plot.plot({
marginLeft: 50,
height: 300,
x: { label: "Quarter", type: "utc" },
y: { label: "Count" },
color: {
domain: ["Acting", "Vacant"],
range: ["#C06840", "#B85C5C"],
legend: true
},
marks: [
Plot.line(timelineData, {
x: "date",
y: "count",
stroke: "series",
strokeWidth: 2
}),
Plot.dot(timelineData, {
x: "date",
y: "count",
fill: "series",
r: 3
})
]
})Data Table
Inputs.table(tableFiltered, {
columns: ["name", "position_title", "department", "administration", "status", "days_served"],
header: {
name: "Name",
position_title: "Position",
department: "Department",
administration: "Administration",
status: "Status",
days_served: "Days Served"
},
sort: "days_served",
reverse: true,
rows: 20
})Note: Sample data is shown for demonstration purposes. This data is mock/simulated and does not represent actual appointee records.