CS-GY 6313 - Information Visualization
New York University
2026-10-02
| User Interface | Graphics Library | Notebook |
|---|---|---|
| observablehq.com | D3 | Week 5 Lab Notebook |
Today we will be a coding-heavy lab where we will practice with color scales and geodata. The lab will be divided into these sessions:
D3.js scales are intended to map data domain → screen range
Common types:
| Code | Data Type Compatibility |
|---|---|
d3.scaleLinear() |
Numeric data |
d3.scaleLog() |
Skewed numeric data (e.g. income) |
d3.scaleTime() |
Time/date axes |
d3.scaleLinear()
.domain([0,10])
.range([0, 100])
// linear_scale_example(5) → 50
// linear_scale_example(3) → 30In this coding session, you will be practicing with producing a scatter plot based on health data from different countries/regions. This session uses the gapminder data.
An initialized chart with titles, but it’s missing the axes and data.
d3.scaleLinear(), d3.scaleLog())domain() and range() when setting up plot axes.Sequential scales are used with numeric, continuous data to generate gradients:


This is generally good for:
Use combinations such as d3.scaleOrdinal() + d3.schemeCategory10 to map ordinal or nominal data to specific colors.
Other categorical schemes provided here.
Categorical scale are good for:
| Category | D3 scale | Typical use |
|---|---|---|
| Continuous | d3.scaleLinear() |
Numeric → numeric/color/etc. |
d3.scalePow() |
Power-transformed quantitative data | |
d3.scaleSqrt() |
Square-root scaling, especially symbol area | |
d3.scaleLog() |
Data spanning orders of magnitude | |
d3.scaleSymlog() |
Log-like scaling that can handle zero/negative values | |
d3.scaleRadial() |
Radial visual encodings | |
d3.scaleIdentity() |
Domain and range are identical | |
| Temporal | d3.scaleTime() |
Dates/times using local time |
d3.scaleUtc() |
Dates/times using UTC | |
| Sequential | d3.scaleSequential() |
Continuous values → sequential interpolator |
d3.scaleSequentialLog() |
Sequential + logarithmic transform | |
d3.scaleSequentialPow() |
Sequential + power transform | |
d3.scaleSequentialSqrt() |
Sequential + square-root transform | |
d3.scaleSequentialSymlog() |
Sequential + symmetric-log transform | |
d3.scaleSequentialQuantile() |
Quantile-based sequential encoding | |
| Diverging | d3.scaleDiverging() |
Continuous values around a meaningful midpoint |
d3.scaleDivergingLog() |
Diverging + logarithmic transform | |
d3.scaleDivergingPow() |
Diverging + power transform | |
d3.scaleDivergingSqrt() |
Diverging + square-root transform | |
d3.scaleDivergingSymlog() |
Diverging + symmetric-log transform | |
| Discrete / categorical | d3.scaleOrdinal() |
Categories → arbitrary discrete values/colors |
d3.scaleBand() |
Categories → evenly spaced bands | |
d3.scalePoint() |
Categories → evenly spaced points | |
| Discretizing | d3.scaleQuantize() |
Continuous domain → fixed number of discrete bins |
d3.scaleQuantile() |
Continuous distribution → equal-count bins | |
d3.scaleThreshold() |
User-defined thresholds → discrete values |
Remember the core principles of domain, range, and scale:
Everything in D3.js, from the X-axis to the Y-axis to the color scale, relies on this pattern.
What is a Choropleth Map?
Example Src: D3

In the example, we plotted a simple Mercator map. In this coding session, we will make it more interesting by binding the geodata to another dataset: population.
If you recall in Week 3 Exercise,, we generated the geomap of USA counties and their population data. To achieve this, we needed to link the population data to the geodata by some common feature. In that case, we joined the two datasets based on an id feature that was basically the zip codes of each USA county.
In this coding session, we will do something similar, but in D3 and using a world map instead of the USA counties map. We have provided the basic code for the Mercator map both in the example above and in this code session’s starter code. It’s your job to color the countries of the map to show their population sizes.
The barebones code for the Mercator map.
Map() to act as a lookup dictionary when mapping countries to populations.Image src: “Color Advice for Data Visualization with D3.js” by Elijah Meeks


In this section, we’ll be copying the scatter plot data used in Coding Session #1 but with some different twists. In the first coding session, you were tasked with using either d3.sequentialBlues for the health data or d3.schemeCategory10 for the categorical region data. However, many of these pre-determined schema can be hard to visually parse for people with ocular deficiencies such as color blindness.
To simulate the different variations of color blindness, you can go to this website. This is a very useful simulator that alters a sample image to let you see what certain ocular conditions look like.
For this coding session, you will copy-paste your code from Coding Session #1 and modify it to use a color scheme that aims to make the coloration accessible to people with Deuteranopia (green-blindness). One way we can do this is to use ColorBrewer palettes. For more information, look at this repository of different color palettes and search for “ColorBrewer”.
Once you have what you believe is an acceptable color visualization, hop over to https://bioapps.byu.edu/colorblind_image_tester and upload a PNG of your plot to receive a rating of whether it’s friendly or not to people with Deuteranopia.
