Data Visualization Best Practices
Expert guidance for creating publication-quality scientific visualizations, avoiding common pitfalls, and optimizing figure clarity.
When to Use This Skill
- Creating figures for scientific publications
- Debugging misleading or distorted visualizations
- Optimizing figure layouts and element sizes
- Choosing appropriate plot types for data characteristics
- Ensuring statistical annotations fit properly
- Generating images for sharing with Claude or other AI tools
Supporting Files
This skill is organized into focused reference files. Load them as needed:
- pitfalls-and-troubleshooting.md - Log-scale distortion, coordinate transform bugs, outlier handling philosophy, axis range optimization, float year labels
- chart-recipes.md - Code recipes for temporal trends, boxplots, scatter plots, category proportions, stacked area charts, sample size legends, the dual-approach for outlier handling in publication figures
- color-palettes.md - Okabe-Ito palette, Paul Tol palette, sequential/diverging schemes, colorblind-safe implementation in matplotlib/seaborn
- claude-image-constraints.md - Claude API 8000px limit, safe figure size presets, resize helpers, Jupyter notebook oversized image fixes
- figure-descriptions.md - Templates for writing publication-quality figure descriptions with proper statistical reporting
- itol-reference.md - iTOL dataset formats (DATASET_STYLE, DATASET_BINARY, DATASET_COLORSTRIP), species name synchronization, troubleshooting
- journal-requirements.md - Journal-specific figure specs (Nature, Science, Cell, PLOS, ACS, IEEE, Elsevier, BMC): dimensions, DPI, formats, panel labeling, file naming
Assets (importable in notebooks/scripts)
assets/publication.mplstyle - General publication style: plt.style.use('path/to/publication.mplstyle')
assets/nature.mplstyle - Nature journal style (89mm single column, 7pt fonts, 600 DPI)
assets/presentation.mplstyle - Larger fonts/lines for posters and slides
assets/color_palettes.py - Importable palette definitions (Okabe-Ito, Wong, Paul Tol), apply_palette() helper, DNA base colors
Scripts (helper utilities)
scripts/figure_export.py - save_publication_figure(), save_for_journal(), check_figure_size() - export in multiple formats with journal-specific DPI/format settings
scripts/style_presets.py - apply_publication_style(), configure_for_journal(), set_color_palette() - one-command journal configuration
Core Principles
1. Always Check Log-Scale Plots
KDE-based plots (violin, ridge) on log axes produce distorted shapes. Use boxplots or log-transform data first, then plot on linear axes. See pitfalls-and-troubleshooting.md for details.
2. Show All Data First, Filter Later
Default to showing ALL data points in initial visualizations (showfliers=True). Outliers may be biologically meaningful. Only filter after review with domain expert, and always document exclusions.
3. Use Colorblind-Safe Palettes
Use Okabe-Ito palette (recommended by Nature) for categorical data. Combine color with marker shapes for redundancy. Never use red-green combinations. See color-palettes.md for hex codes and implementation.
4. Respect Claude's Image Size Limit
Images shared with Claude must not exceed 8000 pixels in either dimension. Use safe figure size presets and the save_figure() helper. See claude-image-constraints.md.
5. Position Annotations Carefully
Use pure data coordinates or ax.transAxes (0-1 range) for text positioning. Never mix coordinate systems (e.g., ax.get_xaxis_transform() with data-scale y-values). See pitfalls-and-troubleshooting.md.
Chart Selection Quick Guide
| Data Type |
Recommended Chart |
When to Use |
| Distribution comparison |
Boxplot |
Large datasets, log scales, multiple groups |
| Distribution shape |
Histogram |
Always works on log scales, shows true frequency |
| Temporal trends (few points) |
Scatter + regression |
< 50 points per timepoint, continuous time |
| Temporal trends (many points) |
Boxplots by year |
Overlapping points, discrete timepoints |
| Category proportions over time |
Stacked area + stacked bar (dual panel) |
Showing both relative and absolute trends |
| Categorical comparison |
Bar chart, violin (linear scale only) |
Group means or distributions |
| Phylogenetic annotation |
iTOL datasets |
Tree visualization with metadata |
Publication Figure Checklist
Before Creating
During Creation
After Creation
For Temporal Analyses
Quick Reference: Safe Figure Sizes (300 DPI)
FIG_SIZES = {
'single_column': (3.5, 4), # 1050x1200 px
'double_column': (7, 5), # 2100x1500 px
'full_page': (7, 9), # 2100x2700 px
'poster': (20, 15), # 6000x4500 px
'max_claude': (26, 26), # 7800x7800 px
}
Quick Reference: Okabe-Ito Colors (3 Categories)
colors = {
'Category_A': '#0072B2', # Blue
'Category_B': '#E69F00', # Orange
'Category_C': '#CC79A7' # Reddish Purple
}
Best Practices Summary
- Always check log-scale plots - Verify KDE-based plots against histograms
- Test element sizes - Regenerate with different sizes for optimal clarity
- Explicit axis limits - Don't rely on auto-limits when annotations are added
- Consistent styling - Use seaborn context and style for publication consistency
- High DPI - Save at 300 DPI minimum (
dpi=300, bbox_inches='tight')
- Optimize axis ranges - Zoom to data range when distributions are compressed
- Check image dimensions - Verify size before sharing with Claude (max 7999x7999)
- Set size constraints - Use safe figure sizes when generating images programmatically
- Temporal trends with outliers - Create both cleaned (publication) and full (verification) versions
- Include sample sizes - Always show n= in legends for comparative figures
References
1---
2name: data-visualization
3description: Best practices for creating clear, accurate scientific visualizations with matplotlib, seaborn, and other Python plotting libraries. Covers common pitfalls, optimization techniques, publication-quality figure generation, and Claude API image size constraints.
4version: 1.2.0
5context: fork
6allowed-tools: Read, Grep, Glob, Bash
7---
8
9# Data Visualization Best Practices
10
11Expert guidance for creating publication-quality scientific visualizations, avoiding common pitfalls, and optimizing figure clarity.
12
13## When to Use This Skill
14
15- Creating figures for scientific publications
16- Debugging misleading or distorted visualizations
17- Optimizing figure layouts and element sizes
18- Choosing appropriate plot types for data characteristics
19- Ensuring statistical annotations fit properly
20- Generating images for sharing with Claude or other AI tools
21
22## Supporting Files
23
24This skill is organized into focused reference files. Load them as needed:
25
26- **[pitfalls-and-troubleshooting.md](pitfalls-and-troubleshooting.md)** - Log-scale distortion, coordinate transform bugs, outlier handling philosophy, axis range optimization, float year labels
27- **[chart-recipes.md](chart-recipes.md)** - Code recipes for temporal trends, boxplots, scatter plots, category proportions, stacked area charts, sample size legends, the dual-approach for outlier handling in publication figures
28- **[color-palettes.md](color-palettes.md)** - Okabe-Ito palette, Paul Tol palette, sequential/diverging schemes, colorblind-safe implementation in matplotlib/seaborn
29- **[claude-image-constraints.md](claude-image-constraints.md)** - Claude API 8000px limit, safe figure size presets, resize helpers, Jupyter notebook oversized image fixes
30- **[figure-descriptions.md](figure-descriptions.md)** - Templates for writing publication-quality figure descriptions with proper statistical reporting
31- **[itol-reference.md](itol-reference.md)** - iTOL dataset formats (DATASET_STYLE, DATASET_BINARY, DATASET_COLORSTRIP), species name synchronization, troubleshooting
32- **[journal-requirements.md](journal-requirements.md)** - Journal-specific figure specs (Nature, Science, Cell, PLOS, ACS, IEEE, Elsevier, BMC): dimensions, DPI, formats, panel labeling, file naming
33
34## Assets (importable in notebooks/scripts)
35
36- **`assets/publication.mplstyle`** - General publication style: `plt.style.use('path/to/publication.mplstyle')`
37- **`assets/nature.mplstyle`** - Nature journal style (89mm single column, 7pt fonts, 600 DPI)
38- **`assets/presentation.mplstyle`** - Larger fonts/lines for posters and slides
39- **`assets/color_palettes.py`** - Importable palette definitions (Okabe-Ito, Wong, Paul Tol), `apply_palette()` helper, DNA base colors
40
41## Scripts (helper utilities)
42
43- **`scripts/figure_export.py`** - `save_publication_figure()`, `save_for_journal()`, `check_figure_size()` - export in multiple formats with journal-specific DPI/format settings
44- **`scripts/style_presets.py`** - `apply_publication_style()`, `configure_for_journal()`, `set_color_palette()` - one-command journal configuration
45
46## Core Principles
47
48### 1. Always Check Log-Scale Plots
49
50KDE-based plots (violin, ridge) on log axes produce distorted shapes. Use boxplots or log-transform data first, then plot on linear axes. See [pitfalls-and-troubleshooting.md](pitfalls-and-troubleshooting.md) for details.
51
52### 2. Show All Data First, Filter Later
53
54Default to showing ALL data points in initial visualizations (`showfliers=True`). Outliers may be biologically meaningful. Only filter after review with domain expert, and always document exclusions.
55
56### 3. Use Colorblind-Safe Palettes
57
58Use Okabe-Ito palette (recommended by Nature) for categorical data. Combine color with marker shapes for redundancy. Never use red-green combinations. See [color-palettes.md](color-palettes.md) for hex codes and implementation.
59
60### 4. Respect Claude's Image Size Limit
61
62Images shared with Claude must not exceed **8000 pixels** in either dimension. Use safe figure size presets and the `save_figure()` helper. See [claude-image-constraints.md](claude-image-constraints.md).
63
64### 5. Position Annotations Carefully
65
66Use pure data coordinates or `ax.transAxes` (0-1 range) for text positioning. Never mix coordinate systems (e.g., `ax.get_xaxis_transform()` with data-scale y-values). See [pitfalls-and-troubleshooting.md](pitfalls-and-troubleshooting.md).
67
68## Chart Selection Quick Guide
69
70| Data Type | Recommended Chart | When to Use |
71|-----------|------------------|-------------|
72| Distribution comparison | Boxplot | Large datasets, log scales, multiple groups |
73| Distribution shape | Histogram | Always works on log scales, shows true frequency |
74| Temporal trends (few points) | Scatter + regression | < 50 points per timepoint, continuous time |
75| Temporal trends (many points) | Boxplots by year | Overlapping points, discrete timepoints |
76| Category proportions over time | Stacked area + stacked bar (dual panel) | Showing both relative and absolute trends |
77| Categorical comparison | Bar chart, violin (linear scale only) | Group means or distributions |
78| Phylogenetic annotation | iTOL datasets | Tree visualization with metadata |
79
80## Publication Figure Checklist
81
82### Before Creating
83
84- [ ] Choose colorblind-safe palette (Okabe-Ito recommended)
85- [ ] Plan figure dimensions within Claude's 8000px limit
86- [ ] Decide on panel layout (side-by-side vs stacked)
87
88### During Creation
89
90- [ ] Include sample sizes in legends: `Category (n=123)`
91- [ ] Use integer year labels: `ax.xaxis.set_major_locator(plt.MaxNLocator(integer=True))`
92- [ ] Set explicit axis limits when adding annotations
93- [ ] Reduce element sizes for dense data (s=25, alpha=0.5)
94- [ ] Use `bbox_inches='tight'` when saving
95
96### After Creation
97
98- [ ] Verify image dimensions (max 7999x7999 for Claude)
99- [ ] Check annotations are within plot bounds
100- [ ] Test colorblind accessibility
101- [ ] Save at 300 DPI minimum for publication
102
103### For Temporal Analyses
104
105- [ ] Create both all-data and cleaned versions
106- [ ] Calculate statistics on FULL dataset (not cleaned)
107- [ ] Document outlier removal method and retention rate
108- [ ] Use clear file naming: `figure.png` vs `figure_clean.png`
109
110## Quick Reference: Safe Figure Sizes (300 DPI)
111
112```python
113FIG_SIZES = {
114 'single_column': (3.5, 4), # 1050x1200 px
115 'double_column': (7, 5), # 2100x1500 px
116 'full_page': (7, 9), # 2100x2700 px
117 'poster': (20, 15), # 6000x4500 px
118 'max_claude': (26, 26), # 7800x7800 px
119}
120```
121
122## Quick Reference: Okabe-Ito Colors (3 Categories)
123
124```python
125colors = {
126 'Category_A': '#0072B2', # Blue
127 'Category_B': '#E69F00', # Orange
128 'Category_C': '#CC79A7' # Reddish Purple
129}
130```
131
132## Best Practices Summary
133
1341. **Always check log-scale plots** - Verify KDE-based plots against histograms
1352. **Test element sizes** - Regenerate with different sizes for optimal clarity
1363. **Explicit axis limits** - Don't rely on auto-limits when annotations are added
1374. **Consistent styling** - Use seaborn context and style for publication consistency
1385. **High DPI** - Save at 300 DPI minimum (`dpi=300, bbox_inches='tight'`)
1396. **Optimize axis ranges** - Zoom to data range when distributions are compressed
1407. **Check image dimensions** - Verify size before sharing with Claude (max 7999x7999)
1418. **Set size constraints** - Use safe figure sizes when generating images programmatically
1429. **Temporal trends with outliers** - Create both cleaned (publication) and full (verification) versions
14310. **Include sample sizes** - Always show n= in legends for comparative figures
144
145## References
146
147- Matplotlib documentation: https://matplotlib.org/
148- Seaborn visualization: https://seaborn.pydata.org/
149- iTOL documentation: https://itol.embl.de/help.cgi
150- Okabe-Ito palette: https://jfly.uni-koeln.de/color/
151- ColorBrewer: https://colorbrewer2.org