Plot = require("@observablehq/plot")
d3 = require("d3@7")
leveldata = transpose(leveldata_raw)
d_output_plot = transpose(d_output_plot_raw)
formatWeek = d3.timeFormat("%e %b %y")
url = "https://simonjackman.github.io/poll_averaging_voice_2023/poll_averaging.html"
Plot.plot(
{
width: 800,
height: 688,
//marginRight: 32,
marginBottom: 88,
y: {
label: "Yes %",
grid: true,
inset: 6
},
x: {
label: null,
round: true,
nice: d3.utcWeek,
type: "utc",
ticks: null,
tickFormat: null
},
marks: [
Plot.axisX(
{
ticks: "year",
tickSize: 28,
tickPadding: -11,
tickFormat: " %Y",
textAnchor: "start"
}
),
Plot.axisX(
{
ticks: "month",
tickSize: 16,
tickPadding: -11,
tickFormat: " %b",
textAnchor: "start"
}
),
Plot.gridX(
{
ticks: "month",
stroke: "black",
strokeOpacity: 0.15,
insetBottom: -0.5
}
),
Plot.areaY(
leveldata,
{
x: "datetime",
y1: "lo",
y2: "up",
fill: "orange",
fillOpacity: 0.25,
filter: (d) =>
d.datetime <= d3.max(d_output_plot.map(d => d.mid_date)),
}
),
Plot.areaY(
leveldata,
{
x: "datetime",
y1: "lo",
y2: "up",
fill: "orange",
fillOpacity: 0.1,
filter: (d) =>
d.datetime > d3.max(d_output_plot.map(d => d.mid_date)),
}
),
Plot.lineY(
leveldata,
{
x: "datetime",
y: "mean",
filter: (d) =>
d.datetime <= d3.max(d_output_plot.map(d => d.mid_date)),
stroke: "black",
strokeWidth: 5
}
),
Plot.lineY(
leveldata,
{
x: "datetime",
y: "mean",
filter: (d) =>
d.datetime > d3.max(d_output_plot.map(d => d.mid_date)),
stroke: "black",
strokeOpacity: 0.25,
strokeWidth: 5
}
),
Plot.ruleY([50]),
Plot.ruleY([45.13]),
Plot.text(
["1999 Republic Yes, 45.1%"],
{
x: new Date("2022-08-01"),
y: 45.13,
dy: -2,
dx: -24,
lineAnchor: "bottom",
textAnchor: "start",
text: (d) => d
}
),
Plot.ruleX(
leveldata,
Plot.pointerX(
{
x: "datetime",
py: "mean",
stroke: "#FF00002F",
strokeWidth: 1
}
)
),
Plot.dot(
leveldata,
Plot.pointerX(
{
x: "datetime",
y: "mean",
r: 6,
stroke: "red",
fill: "black"
}
)
),
Plot.text(
leveldata,
Plot.pointerX(
{
px: "datetime",
py: "mean",
dy: -17,
frameAnchor: "top-right",
fontSize: 14,
text:
(d) => [
`${formatWeek(
d3.utcParse("%Y-%m-%dT%H:%M:%SZ")(d.datetime)
)
}`,
`${
d.datetime > d3.max(d_output_plot.map(d => d.mid_date)) ?
"Forecasted poll average " :
"Poll average "
}` +
`${d.mean.toFixed(1)}%` +
` ± ${d.moe.toFixed(1)}`
].join(" ")
}
)
),
Plot.dot(
d_output_plot,
{
x: "mid_date",
y: "y",
r: 5
}
),
Plot.tip(
d_output_plot,
Plot.pointer(
{
x: "mid_date",
y: "y",
title: (d) =>
[
d.Pollster + " " + d3.format(".1f")(d.y) +"%",
"Start: " + d.FieldedStart,
"End: " + d.FieldedEnd,
"Yes: " + d.Yes_prop,
"No: " + d.No_prop,
"Undecided: " + d.Unsure_prop,
"Sample size: " + d3.format(",d")(d.SampleSize)
].join("\n")
}
)
),
Plot.text(
[
"Poll average computed by " +
"Professor Simon Jackman. "
],
{
frameAnchor: "bottom-left",
dy: 50,
fontSize: 15,
fontColor: "blue",
lineAnchor: "bottom",
text: (d) => d,
href: d => url
}
),
Plot.text(
[
"Data compiled by Casey Briggs, Australian Broadcasting Corporation."
],
{
frameAnchor: "bottom-left",
dy: 50 + 15 + 2,
fontSize: 15,
lineAnchor: "bottom",
text: (d) => d
}
),
Plot.text(
[
"Shaded region is a 95% credible interval. " +
"Roll over points to reveal details of polls."
],
{
frameAnchor: "bottom-left",
dy: 50 + 15 + 15 + 2,
fontSize: 15,
lineAnchor: "bottom",
text: (d) => d
}
)
]
}
)