Public
Edited
May 1, 2022
Insert cell
Insert cell
Insert cell
anom_data = FileAttachment("anom_data.csv").csv()
Insert cell
Insert cell
xAccessor = d => +d.value
Insert cell
yAccessor = d => +d.year
Insert cell
Insert cell
dms = {
let dms = {
width: width,
marginTop: 30,
marginRight: 60,
marginBottom: 30,
marginLeft: 60,
barHeight: 12
};

dms.height = Math.ceil((anom_data.length + 0.1) * dms.barHeight) + dms.marginTop + dms.marginBottom;
dms.boundedWidth = dms.width - dms.marginLeft - dms.marginRight;
dms.boundedHeight = dms.height - dms.marginTop - dms.marginBottom;
return dms;
}
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
Insert cell
xScale = d3.scaleLinear()
.domain(d3.extent(anom_data, xAccessor))
.rangeRound([dms.marginLeft, dms.width - dms.marginRight])
Insert cell
yScale = d3.scaleBand()
.domain(d3.range(anom_data.length))
//.domain(d3.extent(anom_data, yAccessor))
.rangeRound([dms.marginTop, dms.height - dms.marginBottom])
.padding(0.1)
Insert cell
Insert cell
xAxisTop = g => g

// set axis position
.attr("transform", `translate(0,${dms.marginTop})`)
// draw axis
.call(d3.axisTop(xScale)
.ticks(20))
// set axis class for css styling
.attr("class", "axisGroup")
Insert cell
xAxisBottom = g => g
.attr("transform", `translate(0,${dms.height - dms.marginBottom})`)
.call(d3.axisBottom(xScale)
.ticks(20))
.attr("class", "axisGroup")
Insert cell
yAxis = g => g
.attr("transform", `translate(${xScale(0)},0)`)

// draw axis
.call(d3.axisLeft(yScale)
// filter out every other year from the tick labels
.tickFormat((d, i) => i % 2 === 0 ? anom_data[i].year : null)
.tickSize(0)
.tickPadding(6)
)

// move y axis labels to rhs of axis where values are negative
.call(g => g.selectAll(".tick text")
.filter(i => xAccessor(anom_data[i]) < 0)
.attr("text-anchor", "start")
.attr("x", xScale(0.02) - xScale(0)))
.attr("class", "axisGroup")
Insert cell
Insert cell
chart = {

// create svg element to draw within
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, dms.height]);

// create bars
svg.append("g")
.selectAll("rect")
.data(anom_data)
.join("rect")
//.attr("fill", d => d3.schemeSet1[d.value > 0 ? 0 : 1])
.attr("fill", d => xAccessor(d) > 0 ? styling.aboveAveCol : styling.belowAveCol)
.attr("x", d => xScale(Math.min(xAccessor(d), 0)))
.attr("y", (d, i) => yScale(i))
.attr("width", d => Math.abs(xScale(xAccessor(d)) - xScale(0)))
.attr("height", yScale.bandwidth());

// add end of bar text labels
svg.append("g")
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr("class", "barLabelGroup")
.selectAll("text")
.data(anom_data)
.join("text")
// only include labels every other year, so no too crowded
.filter((d, i) => i % 2 === 0 ? yAccessor(d) : null)
.attr("text-anchor", d => xAccessor(d) < 0 ? "end" : "start")
.attr("x", d => xScale(xAccessor(d)) + Math.sign(xAccessor(d) - 0) * 4)

// set position when only labeling some of the bars
.attr("y", (d, i) => yScale(yAccessor(d) - d3.min(anom_data, d => yAccessor(d))) + yScale.bandwidth() / 2)
.attr("dy", "0.35em")
.attr("fill", d => xAccessor(d) > 0 ? styling.aboveAveCol : styling.belowAveCol)
.text(d => styling.format(xAccessor(d)));
//.text(d => d.value);

// add axis
svg.append("g")
.call(xAxisTop);

svg.append("g")
.call(xAxisBottom);

svg.append("g")
.call(yAxis);

return svg;
}
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
Insert cell
chart.node()
Insert cell
Insert cell
styling = {
let styling = { belowAveCol: "#6E99C3",
aboveAveCol: "#E48367",
format: d3.format("+")}
return styling;
}
Insert cell
<style type="text/css">

@import url('https://fonts.googleapis.com/css2?family=Lato&display=swap');

/* set global colours */
:root {
--greyAxis: #808080;
--greyTicks: #CECECE;
}

/* style the x axis */
.axisGroup line{
stroke: var(--greyTicks);
}
.axisGroup path{
stroke: var(--greyAxis);
}
.axisGroup text{
fill: var(--greyAxis);
font-family: 'Lato', sans-serif;
font-size: 13px;
font-weight: 580;
}

.barLabelGroup text{
font-family: 'Lato', sans-serif;
font-size: 12px;
}

.xAxisLab text{
fill: var(--greyAxis);
font-family: 'Lato', sans-serif;
font-size: 20px;
}
</style>
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

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