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:
javascript// 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):
javascriptconst colorblindSafe = [ '#332288', '#117733', '#44AA99', '#88CCEE', '#DDCC77', '#CC6677', '#AA4499', '#882255' ];
Always use redundant encoding - don't rely on color alone:
javascriptnode.attr('fill', d => colorScale(d.category)) .attr('d', d => symbolScale(d.category)); // Shape too!
3. D3.js Patterns
Force Simulation:
javascriptconst 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:
javascriptconst svg = d3.select('#chart') .append('svg') .attr('viewBox', `0 0 ${width} ${height}`) .attr('preserveAspectRatio', 'xMidYMid meet');
Touch-Friendly (44x44px minimum):
javascriptnode.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
bashscripts/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
bashscripts/analyze-distribution.py data.csv --column value # Outputs: min, max, skew ratio, recommended scale
Scaffold D3 Project
bashscripts/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

