Topic 0.2
What a Chart Is
In one line
A chart turns numbers into shapes (lengths, positions, sizes, colours) so the eye can compare them in one look. It answers a question, and it can also hide or bend the answer if it is drawn carelessly.
Think of it like this
A child's growth marks on a door frame. Each mark is a line at the child's height on one birthday. Nobody reads the numbers; you see at once that the marks climb, and that one year they jumped. The door frame is a chart: a number (height) became a position (how high the mark is).
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- data
- The facts you start with, usually numbers in rows: one row per day, per station, per trip.
- value
- One number in the data, such as 2,979 rides on one Monday.
- channel
- The visual property a value controls: length, position, size, colour or shape.
- baseline
- The line that bars grow from. For bars it must be zero, or the lengths stop being honest.
- proportional
- Growing in step: twice the number gives twice the length.
- pattern
- Something regular you can see in the data: a rise, a peak, a repeating weekly wiggle.
- outlier
- A value far away from the others, like one very quiet day in a busy summer.
Step by step
01Start with the same numbers in two forms
The first example takes one week of Lumen Bikes rides (2–8 June 2025) and shows it twice: as a table and as bars.
In the table you read seven numbers and keep them in your head to compare. In the bars you see at once that Monday is shortest and Tuesday longest. Monday was also a rainy day (4.8 mm of rain, from the rain_mm column of the data).
02Turn each number into a length
The code finds the biggest value (3,992 on Tuesday) and gives it 340 pixels. Every other bar gets rides ÷ 3,992 × 340 pixels. So Monday's 2,979 rides become about 254 pixels.
This one line, "value ÷ biggest × space", is the first scale of the course: a rule that turns a number into a size. Topic 3.2 writes it properly, and D3 gives you a ready-made one in Topic 6.1.
const length = (d.rides / most) * 340; // the biggest day gets 340 pixels03Draw 365 numbers as one line
The second example fetches the whole year from daily.csv. Each day becomes one point: day number along x, rides up the y direction. Joining the points gives one line.
SVG's y grows downwards (Topic 1.1), so a busier day needs a smaller y to sit higher. That is why the code writes 150 - (r / most) * 140.
04Spot the surprise
The line rises to a summer peak and falls back. Most wiggles repeat every week. One spike plunges almost to the bottom in August. The code finds the lowest day (Math.min) and prints its date: 2025-08-14, with 439 rides.
05Bend the truth on purpose, then measure it
The third example draws Monday and Tuesday twice: once with bars starting at 0, once starting at 2,900. It measures how much longer Tuesday's bar is in each picture.
Honest bars: 1.3 times as long, the same as the real ratio of rides. Cut bars: 13.8 times as long. Same data, very different story.
Try it yourself
- 1
Make the bars use more space
In the first example, change
* 340to* 200. Every bar shrinks by the same share, and Monday is still the shortest. The rule keeps the comparison honest whatever space you give it. - 2
Move the baseline closer
In the third example, change
draw("cut", 2900)todraw("cut", 2000). The Console now says Tuesday's bar looks 2.0 times as long as Monday's. The closer the baseline gets to zero, the closer the picture gets to the truth (1.3). - 3
Find the busiest day too
In the second example, add
const high = rides.indexOf(Math.max(...rides));andconsole.log("Busiest day:", rows[high].split(",")[0], rides[high]);at the end ofmain. It printsBusiest day: 2025-07-18 4380: the tallest point of the line.
Code & diagrams
No library: plain JavaScript creates each SVG rectangle. Phase 5 lets D3 do this loop for you.
Preview
Console
Nothing logged yet.Expected console output
Quietest day: Mon 2979
Bars drawn: 7The code is inside an async function because this example has no import, so it is a classic script, and a classic script can't use await at the top level (Topic 0.4's Break it shows the error).
Preview
Console
Nothing logged yet.Expected console output
First three rows: [ '2025-01-01,1193,346,16.5,12.9,7.8,Wed', '2025-01-02,1584,464,16.6,10.8,0,Thu', '2025-01-03,1592,399,17,12.2,0,Fri' ]
Days: 365
Lowest day: 2025-08-14 439A failure that prints no error: the chart looks fine and tells the wrong story.
Preview
Console
Nothing logged yet.Expected console output
honest: Tuesday's bar looks 1.3 times as long as Monday's
cut: Tuesday's bar looks 13.8 times as long as Monday's
Real ratio of rides: 1.3Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Start the bars above the smallest value
In the third example, change draw("cut", 2900) to draw("cut", 3000). Monday has only 2,979 rides, which is below the new start.
Myth vs fact
Myth
A chart is just decoration on top of the numbers.
Fact
A chart is a way of reading numbers: it lets the eye compare dozens or thousands of values at once. Decoration that doesn't help that comparison gets in the way.
Myth
If the numbers in the chart are correct, the chart is honest.
Fact
The third example uses correct numbers and still shows a 13.8× difference instead of 1.3×. How numbers become shapes (here, the baseline) decides whether the picture tells the truth.
Myth
Tables are old-fashioned; always draw a chart.
Fact
For looking up exact values, a table is better. Use charts for patterns and comparisons, and keep the exact numbers reachable (a tooltip, a table, Topic 15.3).
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
The "value ÷ max × space" rule is a linear scale with its domain fixed at [0, max]. It silently breaks with an empty array (
Math.max()with no arguments is-Infinity) or when every value is 0 (division by zero givesNaN). Topic 3.2 handles both; D3'sscaleLinearreturns the middle of the range for a zero-width domain instead of NaN. - ▸
A
polylinewith 365 points is one DOM node, which is cheap. 365 separatecircles would be 365 nodes, still fine. The cost question (SVG nodes vs canvas pixels) starts mattering in the thousands and is measured in Topic 12.1. - ▸
Splitting CSV text on
,only works because this file has no commas inside values. Real CSV allows quoted fields such as"2,016"(daily-dirty.csvhas one). Topic 4.2 uses a real CSV parser (d3.csv) for that reason.
Remember this
- 1
The problem this solves: people read digits slowly, one at a time, but they compare lengths and positions almost instantly. A table of 365 numbers hides the pattern; the same numbers as a line show it in a second.
- 2
Numbers become shapes. Every chart picks a visual property for each number: the length of a bar, the position of a dot, the height of a point on a line, the size of a circle, the colour of a square. These properties are called channels (Topic 2.2 ranks them). In a bar chart, the number decides the bar's length; everything else (colour, gap, label) is there to help you read it.
- 3
A chart answers a question. "Which day was quietest last week?" is answered by bars, where you compare lengths. "How did the year go?" is answered by a line, where you follow the rise and fall. Start every chart with the question; the question picks the chart (Topic 2.3).
- 4
Tables still matter. When you need an exact value ("how many rides on Thursday?"), a table wins: you read 3,742 directly. Charts show shape and comparison; tables show exact numbers. Good dashboards give both: the chart for the pattern, the numbers on demand.
- 5
The baseline is part of the truth. A bar's length must be proportional to its number, so bars start at zero. If the bars start at 2,900 instead, a day with 2,979 rides gets a stub and a day with 3,992 gets a long bar: the picture says "almost 14 times more" while the truth is "1.3 times more". The third example below measures exactly that. Topic 2.5 shows the other ways charts mislead.
- 6
The first look reveals the story, and the surprises. The line of Lumen's 365 days shows a summer peak, weekly wiggles, and one deep spike down in August. That spike is a single day: 14 August 2025, the day the app was down. A chart doesn't explain it, but it shows you where to look.
Explain it without notes
What does it mean that a chart "turns numbers into shapes"? Give an example from this topic.
When is a table better than a chart?
Why must bars start at zero? Use the numbers from the third example.
What did the 365-day line show that the table of numbers didn't?
Practice
Change the first example so the bars are drawn from the top down in order of rides (busiest first). Hint: sort a copy of week before drawing.
Write a function barLength(value, biggest, space) that returns the bar length and returns 0 instead of NaN when biggest is 0. Test it with (2979, 3992, 340), (0, 0, 340) and (5, 10, 200).
Trade-offs
- ↔
A chart shows patterns fast but hides exact values; a table shows exact values but hides patterns. Dashboards usually need both.
- ↔
Starting bars at zero sometimes makes small differences hard to see. The honest fix is a chart that doesn't need a zero baseline (a line or dot plot with a labelled axis), not a cut bar.
Done when you can
I can explain how a number becomes the length of a bar.
I can say which question a bar chart and a line chart each answer.
I can show, with numbers, why bars must start at zero.
I can say when a table is the better choice.