Data Visualization Skill
Create beautiful, mathematically elegant, emotionally resonant data visualizations.
Philosophy: "Life is Beautiful"
Every visualization should:
- Reveal truth through data
- Evoke wonder through design
- Respect the viewer through accessibility
- Honor complexity through elegant simplification
Core Capabilities
1. Visual Encoding
Scale Selection:
| Scale | Use When | Example |
|---|---|---|
| Linear | Evenly distributed data | Temperature |
| Log | Multiple orders of magnitude | Population (100 to 1B) |
| Sqrt | Encoding area (circles) | Bubble chart radius |
| Time | Temporal data | Dates |
Perceptual Honesty - Area scales with square of radius, so use sqrt:
// WRONG: Linear radius exaggerates large values
const badScale = d3.scaleLinear().domain([0, max]).range([0, maxRadius]);
// RIGHT: Sqrt maintains perceptual accuracy
const goodScale = d3.scaleSqrt().domain([0, max]).range([0, maxRadius]);
2. Color Design
Palette Types:
- Categorical - Distinct hues for nominal data (max 8)
- Sequential - Single hue gradient for ordered data
- Diverging - Two hues meeting at meaningful midpoint
Colorblind-Safe Palette (8 colors):
const colorblindSafe = [
'#332288', '#117733', '#44AA99', '#88CCEE',
'#DDCC77', '#CC6677', '#AA4499', '#882255'
];
Always use redundant encoding - don't rely on color alone:
node.attr('fill', d => colorScale(d.category))
.attr('d', d => symbolScale(d.category)); // Shape too!
3. D3.js Patterns
Force Simulation:
const simulation = d3.forceSimulation(nodes)
.force('charge', d3.forceManyBody().strength(-300))
.force('link', d3.forceLink(links).id(d => d.id))
.force('center', d3.forceCenter(width/2, height/2))
.force('collision', d3.forceCollide().radius(d => d.r + 2));
Responsive SVG:
const svg = d3.select('#chart')
.append('svg')
.attr('viewBox', `0 0 ${width} ${height}`)
.attr('preserveAspectRatio', 'xMidYMid meet');
Touch-Friendly (44x44px minimum):
node.append('circle')
.attr('class', 'hit-area')
.attr('r', Math.max(actualRadius, 22))
.attr('fill', 'transparent');
4. Narrative Structure
Three Acts:
- Invitation - What draws viewer in? Why should they care?
- Discovery - What patterns emerge? What surprises?
- Reflection - What should they feel/understand/do?
Progressive Disclosure:
Level 1: Overview → Level 2: Exploration → Level 3: Detail → Level 4: Context
5. Data Pipeline
Structure:
scripts/
├── 01_fetch_raw.py # API calls with caching
├── 02_clean_data.py # Transformation
├── 03_validate.py # Quality checks
└── 04_export.py # Final format
Source Documentation (every dataset needs):
- URL, access date, update frequency
- License and confidence level
- Field descriptions and limitations
Scripts
Generate Color Palette
scripts/color-palette.py --type sequential --hue blue --steps 9
scripts/color-palette.py --type categorical --count 6 --colorblind-safe
scripts/color-palette.py --type diverging --low red --high blue
Analyze Data Distribution
scripts/analyze-distribution.py data.csv --column value
# Outputs: min, max, skew ratio, recommended scale
Scaffold D3 Project
scripts/d3-scaffold.py my-viz --type force-network
scripts/d3-scaffold.py my-viz --type timeline
scripts/d3-scaffold.py my-viz --type choropleth
Anti-Patterns to Avoid
- 3D charts (distorts perception)
- Pie charts with >6 categories
- Dual y-axes
- Rainbow color scales (perceptually uneven)
- Truncated y-axes without disclosure
- Animation without purpose
Quality Checklist
- Scale choice justified for data distribution
- Color palette is colorblind-safe
- Minimum 44x44px touch targets
- Clear entry point for viewer
- Sources documented
- Responsive on mobile