Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
//Jan = fetch(`https://api.oireachtas.ie/v1/questions?date_start=${year.value}-01-01&date_end=${year.value}-01-31&limit=9999&qtype=oral,written`).then((response) => response.json())
Insert cell
Insert cell
Insert cell
//Feb = fetch(`https://api.oireachtas.ie/v1/questions?date_start=${year.value}-02-01&date_end=${year.value}-02-28&limit=9999&qtype=oral,written`).then((response) => response.json())
Insert cell
Insert cell
Insert cell
//leapData = leap.results.filter(d => d.contextDate == `${leapYearDateCheck}`)
Insert cell
//Mar = fetch(`https://api.oireachtas.ie/v1/questions?date_start=${year.value}-03-01&date_end=${year.value}-03-31&limit=9999&qtype=oral,written`).then((response) => response.json())
Insert cell
//Apr = fetch(`https://api.oireachtas.ie/v1/questions?date_start=${year.value}-04-01&date_end=${year.value}-04-30&limit=9999&qtype=oral,written`).then((response) => response.json())
Insert cell
//May = fetch(`https://api.oireachtas.ie/v1/questions?date_start=${year.value}-05-01&date_end=${year.value}-05-31&limit=9999&qtype=oral,written`).then((response) => response.json())
Insert cell
//Jun = fetch(`https://api.oireachtas.ie/v1/questions?date_start=${year.value}-06-01&date_end=${year.value}-06-30&limit=9999&qtype=oral,written`).then((response) => response.json())
Insert cell
//Jul = fetch(`https://api.oireachtas.ie/v1/questions?date_start=${year.value}-07-01&date_end=${year.value}-07-31&limit=9999&qtype=oral,written`).then((response) => response.json())
Insert cell
//Aug = fetch(`https://api.oireachtas.ie/v1/questions?date_start=${year.value}-08-01&date_end=${year.value}-08-31&limit=9999&qtype=oral,written`).then((response) => response.json())
Insert cell
//Sep = fetch(`https://api.oireachtas.ie/v1/questions?date_start=${year.value}-09-01&date_end=${year.value}-09-30&limit=9999&qtype=oral,written`).then((response) => response.json())
Insert cell
//Oct = fetch(`https://api.oireachtas.ie/v1/questions?date_start=${year.value}-10-01&date_end=${year.value}-10-31&limit=9999&qtype=oral,written`).then((response) => response.json())
Insert cell
//Nov = fetch(`https://api.oireachtas.ie/v1/questions?date_start=${year.value}-11-01&date_end=${year.value}-11-30&limit=9999&qtype=oral,written`).then((response) => response.json())
Insert cell
//Dec = fetch(`https://api.oireachtas.ie/v1/questions?date_start=${year.value}-12-01&date_end=${year.value}-12-31&limit=9999&qtype=oral,written`).then((response) => response.json())
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
joinedPQs = fetch(
`https://raw.githubusercontent.com/bubcass/PQs/refs/heads/main/PQs_2025_paginated.json`
).then((response) => response.json())
Insert cell
//joinedPQs = [
...Jan.results,
...Feb.results, //...leapData,
...Mar.results,
...Apr.results,
...May.results,
...Jun.results,
...Jul.results,
...Aug.results,
...Sep.results,
...Oct.results,
...Nov.results,
...Dec.results
]
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
dataWithURL = filterTD.flatMap((d) => ({
department: d.question.to.showAs,
heading: d.question.debateSection.showAs,
deputy: d.question.by.showAs,
question: d.question.showAs,
url:
"https://www.oireachtas.ie/en/debates/question/" +
d.contextDate +
"/" +
d.question.questionNumber +
"/",
date: d.contextDate
}))
Insert cell
filteredData = dataWithURL.filter((d) => d.heading.toLowerCase().includes(""))
Insert cell
experimental = ({
name: "Parliamentary Questions",
children: Array.from(
d3.rollup(
dataWithURL,
(v) => v, // Preserve all entries at the final level
...keysToGroupBy1
),
([name, children]) => ({
name,
children: Array.from(children, ([name, children]) => ({
name,
children: Array.from(children, ([name, children]) => ({
name,
children: Array.from(children, ([name, children]) => ({
name,
children: Array.from(children, ([key, values]) => ({
name: values[0].question, // Make sure `name` aligns with your structure
value: values.length, // Use values length if counting
url: values[0].url // Ensure this maps directly to the URL field
}))
}))
}))
}))
})
)
})
Insert cell
Insert cell
keysToGroupBy1 = [
(d) => d.department,
(d) => d.heading,
(d) =>
new Date(d.date).toLocaleString(undefined, {
weekday: "long",
day: "numeric",
month: "long"
}),
(d) => d.deputy,
(d) => d.question
]
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
//import {constituencyGroup} from "05e1988c11cde88e"
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
questionsForML = Array.from(d3.flatRollup(joinedPQs, v => v.length,
d => d.question.showAs,
d => d.question.debateSection.showAs,
d => d.question.to.showAs,
),
([question, heading, department]) => ({question, heading, department}))
Insert cell
ML_csv = questionsForML.slice(-1200).map((d) => ({
question: d.question,
heading: null,
department: d.department
}))
Insert cell
//treemapChart1 = {
const x = d3.scaleLinear().rangeRound([0, width]);
const y = d3.scaleLinear().rangeRound([0, height]);

const svg = d3.create("svg")
.attr("viewBox", [0.5, -30.5, width, height + 30])
.style("font", "16px IBM Plex Sans")
.attr("fill", "white");

let group = svg.append("g")
.call(render, treemap(data));

function render(group, root) {
const node = group
.selectAll("g")
.data(root.children.concat(root))
.join("g");

node.filter(d => d === root ? d.parent : d.children)
.attr("cursor", "pointer")
.on("click", (event, d) => d === root ? zoomout(root) : zoomin(d));

node.append("title")
.text(d => `${name(d)}\n${format(d.value)}`);

node.append("rect")
.attr("id", d => (d.leafUid = DOM.uid("leaf")).id)
.attr("fill", d => d === root ? "#1f77b4" : d.children ? "#1f77b4" : "#7f7f7f")
.attr("stroke", "#ff7f0e")
.attr("stroke-width", 2);

node.append("clipPath")
.attr("id", d => (d.clipUid = DOM.uid("clip")).id)
.append("use")
.attr("xlink:href", d => d.leafUid.href);

node.append("text")
.attr("clip-path", d => d.clipUid)
.attr("font-weight", d => d === root ? "bold" : null)
.selectAll("tspan")
.data(d => (d === root ? name(d) : d.data.name).split(/(?=[A-Z][^A-Z])/g).concat(format(d.value)))
.join("tspan")
.attr("x", 3)
.attr("y", (d, i, nodes) => `${(i === nodes.length - 1) * 0.3 + 1.1 + i * 0.9}em`)
.attr("fill-opacity", (d, i, nodes) => i === nodes.length - 1 ? 0.7 : null)
.attr("font-weight", (d, i, nodes) => i === nodes.length - 1 ? "normal" : null)
.text(d => d);

group.call(position, root);
}

function position(group, root) {
group.selectAll("g")
.attr("transform", d => d === root ? `translate(0,-30)` : `translate(${x(d.x0)},${y(d.y0)})`)
.select("rect")
.attr("width", d => d === root ? width : x(d.x1) - x(d.x0))
.attr("height", d => d === root ? 35 : y(d.y1) - y(d.y0));
}

// When zooming in, draw the new nodes on top, and fade them in.
function zoomin(d) {
const group0 = group.attr("pointer-events", "none");
const group1 = group = svg.append("g").call(render, d);

x.domain([d.x0, d.x1]);
y.domain([d.y0, d.y1]);

svg.transition()
.duration(750)
.call(t => group0.transition(t).remove()
.call(position, d.parent))
.call(t => group1.transition(t)
.attrTween("opacity", () => d3.interpolate(0, 1))
.call(position, d));
}


// When zooming out, draw the old nodes on top, and fade them out.
function zoomout(d) {
const group0 = group.attr("pointer-events", "none");
const group1 = group = svg.insert("g", "*").call(render, d.parent);

x.domain([d.parent.x0, d.parent.x1]);
y.domain([d.parent.y0, d.parent.y1]);

svg.transition()
.duration(750)
.call(t => group0.transition(t).remove()
.attrTween("opacity", () => d3.interpolate(1, 0))
.call(position, d))
.call(t => group1.transition(t)
.call(position, d.parent));
}

return svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
constituencyGroup34.map((d) => ({
name: d.name,
memberCode: d.memberCode,
party: d.party,
partyCode: d.partyCode,
constituency: d.constituency
}))
Insert cell
import { constituencyGroup34 } from "e5830d8f0a1d9a99"
Insert cell
constituencyGroup34
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