Economics Visualization
Generate publication-quality figures that come out of code and \includegraphics{} cleanly into the paper or \frame{} into the slides. The default style follows DIME's Data Visualization and Reviewing Graphs checklist guidance.
Operating Principles
- Figures are produced, never screenshotted. Same DIME four-tier replicability as tables: full replicability means the script writes a vector file (
.pdf/.eps/.svg) directly to paper/figs/.
- Vector first. Save as PDF (or EPS for some journals; SVG for web). PNG only for raster content (maps, photos, screenshots).
- Color discipline. Use a colorblind-safe palette by default (Okabe-Ito, viridis); reserve color for information; ensure the figure still reads in grayscale; never red-green for treatment-vs-control.
- Audience-aware annotation. A figure embedded in a paper relies on the caption; a standalone figure (slide, dashboard, blog) needs an in-figure title, takeaway annotation, and source citation.
- Same dimensions everywhere. Define one figure-size convention per project (e.g.
width = 6.5 in, height = 4 in for paper figures; width = 10 in, height = 5 in for 16:9 slides) so every figure aligns visually.
Decision Policy
This skill follows the repo-wide Agent Policy.
ASK before proceeding (blocking):
- The single point the figure makes. (One figure, one claim.)
- Audience: paper figure (rely on caption) vs standalone (needs in-figure title + source).
- Chart type when more than one would work (e.g. event-study coefficient plot vs forest plot).
- Color encoding — does color carry information, or is it decorative.
DEFAULT + flag (use this default; tell the user how to override):
- Okabe-Ito colorblind-safe palette; never red-green for treatment/control.
- Vector PDF (
device = cairo_pdf in R; default in matplotlib) for paper figures.
- Paper figure dimensions
width = 6.5 in, height = 4 in; slide figures width = 10 in, height = 5.5 in.
theme_paper() in R / paper-wide rcParams in matplotlib / scheme(white_tableau) in Stata.
- Output to
paper/figs/<name>.pdf; the paper \includegraphics{} directly.
DOCUMENT and proceed (write into the figure script header):
- Sample / filter applied for this specific figure (when different from the main estimation sample).
- Source of any external macro variable (e.g. NBER recession dates).
- Color and shape encoding choices for any non-default series.
PROCEED items: figures produced by code (never screenshotted); save vector format; here::here() / pathlib for paths; one script per figure; rebuild path runs figure scripts before LaTeX.
Pre-flight Checklist
Before generating code, confirm with the user — and write the answers in the script header:
- Question the figure answers. A figure should make exactly one point.
- Chart type. Line / bar / scatter / coefficient plot / event study / binscatter / map / density / heatmap?
- Data source and sample. Where does the data come from; what filters apply?
- Audience. Paper figure (rely on caption) or standalone (needs title + source)?
- Output target. PDF for paper; PDF or PNG for slides; SVG for web.
- Dimensions. Width/height in inches; affects font sizing.
- Color encoding. Is color carrying information (yes → palette choice matters) or is it decorative (no → use a single accent color)?
Decision Tree (chart type by question)
Comparing two groups over time
└── Two-line plot with vertical reference line at the event.
Add a shaded confidence band if you have one.
Treatment effect dynamics (event study)
└── Coefficient plot: x = relative period, y = coefficient,
error bars = 95% CI, vertical line at -1 (omitted period).
Magnitude of one effect across many specifications
└── Coefficient plot: y axis lists specifications, x axis shows
point estimate + 95% CI; vertical line at 0.
Distribution of a variable in two groups
└── Overlapping density plots, or a violin plot if N is large.
Continuous-X relationship (with many obs)
└── Binscatter (binsreg in Stata; binsreg / binscatter in R).
Heterogeneity across categories
└── Forest plot (coefplot per category, sorted by point estimate).
Geographic variation
└── Choropleth (sf + ggplot2 in R; geopandas in Python; spmap in Stata).
Cross-section relationship
└── Scatter + line of best fit; consider log scales for skewed vars.
Time series with macro events
└── Line plot with shaded recession bars (NBER dates) and
annotated key events.
Project Layout
paper/
├── paper.tex
├── figs/ # all .pdf figures; never hand-edited
│ ├── fig_event_study.pdf
│ ├── fig_balance.pdf
│ └── fig_time_series.pdf
└── code/
├── r/
│ └── make_figures.R
└── stata/
└── make_figures.do
In the paper:
\begin{figure}[htbp]\centering
\includegraphics[width=0.85\textwidth]{figs/fig_event_study.pdf}
\caption{Event study of treatment effect on outcome Y.}
\label{fig:event}
\end{figure}
Color Palettes (colorblind-safe defaults)
R, ggplot2:
scale_color_manual(values = c("#0072B2", "#D55E00", "#009E73",
"#F0E442", "#CC79A7", "#56B4E9"))
# Okabe-Ito, used by default in scientific publishing.
Python, matplotlib:
plt.rcParams["axes.prop_cycle"] = cycler(
color = ["#0072B2", "#D55E00", "#009E73", "#F0E442",
"#CC79A7", "#56B4E9"])
Sequential numeric (viridis):
ggplot2: scale_*_viridis_c()
matplotlib: cmap = "viridis"
Stata: graph twoway, ... scheme(white_tableau)
Never use a red-green encoding for treatment/control — fails for ~8% of male readers.
Output Skeleton (R, ggplot2)
# make_figures.R header
# Project: ProjectABC
# Inputs : data/processed/analysis.parquet
# Outputs: paper/figs/fig_event_study.pdf
# Author : First Last
# Notes : One figure per script section. Run as a whole.
library(ggplot2)
library(arrow)
library(here)
FIGS <- here("paper", "figs")
dir.create(FIGS, recursive = TRUE, showWarnings = FALSE)
theme_paper <- function(base_size = 11) {
theme_minimal(base_size = base_size) +
theme(panel.grid.minor = element_blank(),
plot.title = element_text(face = "plain"),
plot.title.position = "plot",
legend.position = "bottom")
}
# (figure code)
ggsave(file.path(FIGS, "fig_event_study.pdf"),
width = 6.5, height = 4, units = "in", device = cairo_pdf)
Common Pitfalls
- Default ggplot/matplotlib themes for journal figures (gray panels, busy gridlines). Strip them.
- 3D bar charts and pie charts. Almost never the right choice.
- Two y-axes encoding different units. Hard to interpret; consider faceting instead.
- Tiny axis text on a paper figure that becomes unreadable when the page is printed.
- Inconsistent axis ranges between related figures. Force shared limits.
- Using "rainbow" colormaps (
jet) — perceptually misleading. Use viridis/cividis.
- Forgetting to label units (
Percent, USD, Log GDP).
- Including a legend with one entry. Use a direct title instead.
- Saving as PNG for a paper figure. Use PDF/EPS so the figure scales without pixelation.
- Pasting a figure that requires the audience to read tiny coefficient labels — replace with a coefficient plot.
Additional Resources
reference.md — extended patterns: event-study coefplot recipes, binscatter, recession-shaded time series, balance plot, choropleth maps, faceting.
examples/ — runnable scripts:
examples/event_study_ggplot.R — coefficient plot from fixest::iplot data
examples/balance_plot_ggplot.R — standardized differences plot
examples/time_series_recessions.R — line plot with shaded NBER recessions
examples/binscatter_ggplot.R — binsreg-style scatter
examples/event_study_matplotlib.py — same in Python
examples/coefplot_stata.do — Stata coefplot from eststo output
examples/twoway_stata.do — Stata twoway chart with shaded periods
examples/theme_paper.R — paper-wide ggplot2 theme
Requirements
- R:
ggplot2, arrow, dplyr, here, viridis, sf, binsreg (optional).
- Python:
matplotlib, seaborn, pandas, pyarrow, geopandas (for maps).
- Stata:
coefplot, binsreg, spmap, colorpalette (in palettes package).
- LaTeX:
graphicx, caption, subcaption.
References
DIME
Style and Theory
Tools
1---2name: econ-visualization3description: Generates publication-quality economics figures produced by code (R `ggplot2`, Python `matplotlib`/`seaborn`, Stata `twoway`/`coefplot`) and exported in vector format directly to the paper's `figs/` folder. Defaults to DIME's "full replicability" tier and the [Reviewing Graphs checklist](https://dimewiki.worldbank.org/Checklist:_Reviewing_Graphs) — clear titles for standalone use, intuitive colors, colorblind-safe palettes, consistent axis labels, source citations on standalone visuals, and visualization choices grounded in the [Data Visualization](https://dimewiki.worldbank.org/Data_visualization) wiki page. Use when the user asks for event-study coefficient plots, balance plots, time series with recession shading, choropleth maps, binscatters, density plots, scatter-with-fit, regression coefficient plots, or any reproducible figure for a paper, slide deck, or dashboard.4---56# Economics Visualization78Generate publication-quality figures that come out of code and `\includegraphics{}` cleanly into the paper or `\frame{}` into the slides. The default style follows DIME's [Data Visualization](https://dimewiki.worldbank.org/Data_visualization) and [Reviewing Graphs checklist](https://dimewiki.worldbank.org/Checklist:_Reviewing_Graphs) guidance.910## Operating Principles11121. **Figures are produced, never screenshotted.** Same DIME [four-tier replicability](https://dimewiki.worldbank.org/Exporting_Analysis) as tables: full replicability means the script writes a vector file (`.pdf`/`.eps`/`.svg`) directly to `paper/figs/`.132. **Vector first.** Save as PDF (or EPS for some journals; SVG for web). PNG only for raster content (maps, photos, screenshots).143. **Color discipline.** Use a colorblind-safe palette by default (Okabe-Ito, viridis); reserve color for information; ensure the figure still reads in grayscale; never red-green for treatment-vs-control.154. **Audience-aware annotation.** A figure embedded in a paper relies on the caption; a standalone figure (slide, dashboard, blog) needs an in-figure title, takeaway annotation, and source citation.165. **Same dimensions everywhere.** Define one figure-size convention per project (e.g. `width = 6.5 in, height = 4 in` for paper figures; `width = 10 in, height = 5 in` for 16:9 slides) so every figure aligns visually.1718## Decision Policy1920This skill follows the repo-wide [Agent Policy](../../AGENT_POLICY.md).2122**ASK before proceeding** (blocking):23241. The single point the figure makes. (One figure, one claim.)252. Audience: paper figure (rely on caption) vs standalone (needs in-figure title + source).263. Chart type when more than one would work (e.g. event-study coefficient plot vs forest plot).274. Color encoding — does color carry information, or is it decorative.2829**DEFAULT + flag** (use this default; tell the user how to override):3031- Okabe-Ito colorblind-safe palette; never red-green for treatment/control.32- Vector PDF (`device = cairo_pdf` in R; default in matplotlib) for paper figures.33- Paper figure dimensions `width = 6.5 in, height = 4 in`; slide figures `width = 10 in, height = 5.5 in`.34- `theme_paper()` in R / paper-wide rcParams in matplotlib / `scheme(white_tableau)` in Stata.35- Output to `paper/figs/<name>.pdf`; the paper `\includegraphics{}` directly.3637**DOCUMENT and proceed** (write into the figure script header):3839- Sample / filter applied for this specific figure (when different from the main estimation sample).40- Source of any external macro variable (e.g. NBER recession dates).41- Color and shape encoding choices for any non-default series.4243`PROCEED` items: figures produced by code (never screenshotted); save vector format; `here::here()` / `pathlib` for paths; one script per figure; rebuild path runs figure scripts before LaTeX.4445## Pre-flight Checklist4647Before generating code, confirm with the user — and write the answers in the script header:4849- **Question the figure answers.** A figure should make exactly one point.50- **Chart type.** Line / bar / scatter / coefficient plot / event study / binscatter / map / density / heatmap?51- **Data source and sample.** Where does the data come from; what filters apply?52- **Audience.** Paper figure (rely on caption) or standalone (needs title + source)?53- **Output target.** PDF for paper; PDF or PNG for slides; SVG for web.54- **Dimensions.** Width/height in inches; affects font sizing.55- **Color encoding.** Is color carrying information (yes → palette choice matters) or is it decorative (no → use a single accent color)?5657## Decision Tree (chart type by question)5859```60Comparing two groups over time61└── Two-line plot with vertical reference line at the event.62 Add a shaded confidence band if you have one.6364Treatment effect dynamics (event study)65└── Coefficient plot: x = relative period, y = coefficient,66 error bars = 95% CI, vertical line at -1 (omitted period).6768Magnitude of one effect across many specifications69└── Coefficient plot: y axis lists specifications, x axis shows70 point estimate + 95% CI; vertical line at 0.7172Distribution of a variable in two groups73└── Overlapping density plots, or a violin plot if N is large.7475Continuous-X relationship (with many obs)76└── Binscatter (binsreg in Stata; binsreg / binscatter in R).7778Heterogeneity across categories79└── Forest plot (coefplot per category, sorted by point estimate).8081Geographic variation82└── Choropleth (sf + ggplot2 in R; geopandas in Python; spmap in Stata).8384Cross-section relationship85└── Scatter + line of best fit; consider log scales for skewed vars.8687Time series with macro events88└── Line plot with shaded recession bars (NBER dates) and89 annotated key events.90```9192## Project Layout9394```95paper/96├── paper.tex97├── figs/ # all .pdf figures; never hand-edited98│ ├── fig_event_study.pdf99│ ├── fig_balance.pdf100│ └── fig_time_series.pdf101└── code/102 ├── r/103 │ └── make_figures.R104 └── stata/105 └── make_figures.do106```107108In the paper:109110```latex111\begin{figure}[htbp]\centering112 \includegraphics[width=0.85\textwidth]{figs/fig_event_study.pdf}113 \caption{Event study of treatment effect on outcome Y.}114 \label{fig:event}115\end{figure}116```117118## Color Palettes (colorblind-safe defaults)119120```121R, ggplot2:122 scale_color_manual(values = c("#0072B2", "#D55E00", "#009E73",123 "#F0E442", "#CC79A7", "#56B4E9"))124 # Okabe-Ito, used by default in scientific publishing.125126Python, matplotlib:127 plt.rcParams["axes.prop_cycle"] = cycler(128 color = ["#0072B2", "#D55E00", "#009E73", "#F0E442",129 "#CC79A7", "#56B4E9"])130131Sequential numeric (viridis):132 ggplot2: scale_*_viridis_c()133 matplotlib: cmap = "viridis"134 Stata: graph twoway, ... scheme(white_tableau)135```136137Never use a red-green encoding for treatment/control — fails for ~8% of male readers.138139## Output Skeleton (R, ggplot2)140141```r142# make_figures.R header143# Project: ProjectABC144# Inputs : data/processed/analysis.parquet145# Outputs: paper/figs/fig_event_study.pdf146# Author : First Last147# Notes : One figure per script section. Run as a whole.148149library(ggplot2)150library(arrow)151library(here)152153FIGS <- here("paper", "figs")154dir.create(FIGS, recursive = TRUE, showWarnings = FALSE)155156theme_paper <- function(base_size = 11) {157 theme_minimal(base_size = base_size) +158 theme(panel.grid.minor = element_blank(),159 plot.title = element_text(face = "plain"),160 plot.title.position = "plot",161 legend.position = "bottom")162}163164# (figure code)165166ggsave(file.path(FIGS, "fig_event_study.pdf"),167 width = 6.5, height = 4, units = "in", device = cairo_pdf)168```169170## Common Pitfalls171172- Default ggplot/matplotlib themes for journal figures (gray panels, busy gridlines). Strip them.173- 3D bar charts and pie charts. Almost never the right choice.174- Two y-axes encoding different units. Hard to interpret; consider faceting instead.175- Tiny axis text on a paper figure that becomes unreadable when the page is printed.176- Inconsistent axis ranges between related figures. Force shared limits.177- Using "rainbow" colormaps (`jet`) — perceptually misleading. Use viridis/cividis.178- Forgetting to label units (`Percent`, `USD`, `Log GDP`).179- Including a legend with one entry. Use a direct title instead.180- Saving as PNG for a paper figure. Use PDF/EPS so the figure scales without pixelation.181- Pasting a figure that requires the audience to read tiny coefficient labels — replace with a coefficient plot.182183## Additional Resources184185- `reference.md` — extended patterns: event-study coefplot recipes, binscatter, recession-shaded time series, balance plot, choropleth maps, faceting.186- `examples/` — runnable scripts:187 - `examples/event_study_ggplot.R` — coefficient plot from `fixest::iplot` data188 - `examples/balance_plot_ggplot.R` — standardized differences plot189 - `examples/time_series_recessions.R` — line plot with shaded NBER recessions190 - `examples/binscatter_ggplot.R` — binsreg-style scatter191 - `examples/event_study_matplotlib.py` — same in Python192 - `examples/coefplot_stata.do` — Stata `coefplot` from `eststo` output193 - `examples/twoway_stata.do` — Stata `twoway` chart with shaded periods194 - `examples/theme_paper.R` — paper-wide ggplot2 theme195196## Requirements197198- R: `ggplot2`, `arrow`, `dplyr`, `here`, `viridis`, `sf`, `binsreg` (optional).199- Python: `matplotlib`, `seaborn`, `pandas`, `pyarrow`, `geopandas` (for maps).200- Stata: `coefplot`, `binsreg`, `spmap`, `colorpalette` (in `palettes` package).201- LaTeX: `graphicx`, `caption`, `subcaption`.202203## References204205### DIME206207- DIME Analytics, [Data Visualization](https://dimewiki.worldbank.org/Data_visualization).208- DIME Analytics, [Checklist: Reviewing Graphs](https://dimewiki.worldbank.org/Checklist:_Reviewing_Graphs).209- DIME Analytics, [Exporting Analysis](https://dimewiki.worldbank.org/Exporting_Analysis).210- DIME Analytics, [Stata Visual Library for Impact Evaluation](https://worldbank.github.io/Stata-IE-Visual-Library/).211212### Style and Theory213214- Tufte (2001), *The Visual Display of Quantitative Information*.215- Cleveland (1993), *Visualizing Data*.216- Wilke (2019), *Fundamentals of Data Visualization* — https://clauswilke.com/dataviz/.217- Healy (2018), *Data Visualization: A Practical Introduction* — https://socviz.co/.218- Datawrapper, [What to Consider When Choosing Colors for Data Visualization](https://blog.datawrapper.de/colors/).219- Okabe & Ito, [Color Universal Design palette](https://jfly.uni-koeln.de/color/).220221### Tools222223- ggplot2 — https://ggplot2.tidyverse.org/.224- matplotlib gallery — https://matplotlib.org/stable/gallery/.225- Stata `coefplot` (Jann) — https://repec.sowi.unibe.ch/stata/coefplot/.