Published
Edited
Feb 17, 2021
1 fork
3 stars
Insert cell
md`# Basic bar chart in D3`
Insert cell
chart = {
// draw the svg box with our specified height and width
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);

// grab the svg and draw rectangles
// format the dates nicely for the x axis
// use the values for the y axis
// each rectangle should be the height specified in the value column
// each rectangle should be the width calculated based on how many there are (this will be done automatically!)
svg.append("g")
.attr("fill", "steelblue")
.selectAll("rect")
.data(data)
.join("rect")
.attr("x", d => x(dateFormat(dateParse(d.date))))
.attr("y", d => y(d.value))
.attr("height", d => y(0) - y(d.value))
.attr("width", x.bandwidth());

// draw the y axis
svg.append("g")
.call(yAxis);
// draw the x axis
// label it with rotated text
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.attr("y", 0)
.attr("x", 9)
.attr("dy", ".35em")
.attr("transform", "rotate(60)")
.style("text-anchor", "start");

// draw the chart!
return svg.node();
}
Insert cell
md `#### Read the date from the csv and tell d3 what format it's in`
Insert cell
dateParse = d3.timeParse("%Y-%m")
Insert cell
md `#### Take the parsed date and format it differently`
Insert cell
dateFormat = d3.timeFormat("%B %Y")
Insert cell
daterange = {
return data.map(d => dateFormat(dateParse(d.date)))
}
Insert cell
md `### X axis
This tells d3 that the X axis will be a scale made up of equal bands (good for categorical data).

\`\`.domain()\`\` gets the nicely formatted dates from our transformations above.

\`\`.range()\`\` tells d3 the "physical" space to draw the x axis.

\`\`.padding()\`\` tells d3 to add a little padding between each bar.
`
Insert cell
x = d3.scaleBand()
.domain(daterange)
.range([margin.left, width - margin.right])
.padding(0.1)
Insert cell
xAxis = g => g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x).tickSizeOuter(0))
Insert cell
md `### Y Axis
This tells d3 that the Y axis will be a continuous, linear scale.

\`\`.domain()\`\` tells d3 that the y axis will be labeled starting at 0 and go up to the maximum of the values in the dataset. \`\`d3.max()\`\` tells d3 you're looking for the maximum of whatever is inside the parentheses. \`\`(data, d => +d.value)\`\` gets the dataset, then reads it to find the value column. Our values are formatted as strings rather than numbers, so \`\`+d.value\`\` converts those strings to numbers.

\`\`.range()\`\` tells d3 the "physical" space to draw the y axis.`
Insert cell
y = d3.scaleLinear()
.domain([0, d3.max(data, d => +d.value)])
.range([height - margin.bottom, margin.top])
Insert cell
Insert cell
yAxis = g => g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(y))
.call(g => g.append("text")
.attr("x", -margin.left)
.text(data.y))
Insert cell
md `## Appendix

### Set the variables`
Insert cell
margin = ({top: 30, right: 0, bottom: 80, left: 40})
Insert cell
width = 600 - margin.left - margin.right
Insert cell
height = 500 - margin.top - margin.bottom
Insert cell
md `### Get the data`
Insert cell
data = FileAttachment("data.csv").csv()
Insert cell
md `### Get D3`
Insert cell
d3 = require("d3@6")
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more