用 TikZ 画经济学里的图:供需、博弈树、时间线
经济学论文和讲义里的图,很大一部分不是数据图,而是示意图:一张供需图、一棵博弈树、一条识别设计的时间线。这类图用画图软件拉很难和正文字体统一、放大还糊;用 TikZ 写出来则是矢量的、字体和论文一致、改一个参数图就重排。这篇给三类最常用的图配可直接抄的代码,并把生成出来的样子画给你看。
准备:把图当独立文件编译
强烈建议每张图单独一个 .tex,用 standalone 文档类,编译出一个紧贴内容的 PDF,正文再 \includegraphics 引——这样图能单独调试,也能复用到 slides 里。
\documentclass[tikz,border=2pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows.meta, positioning, calc}
\begin{document}
\begin{tikzpicture}
% 图的代码写这里
\end{tikzpicture}
\end{document}
要画带数据的函数曲线/散点,加 pgfplots(\usepackage{pgfplots} + \pgfplotsset{compat=1.18}),它在 TikZ 之上专门管坐标系。下面三个例子用纯 TikZ 就够。
一、供需图
最常画的图。思路:画两条带箭头的坐标轴,两条直线当供给/需求,标出交点。
\begin{tikzpicture}[>=Stealth, thick]
% 坐标轴
\draw[->] (0,0) -- (6,0) node[right] {$Q$};
\draw[->] (0,0) -- (0,6) node[above] {$P$};
% 需求(向下)与供给(向上)
\draw[blue] (0.5,5) -- (5,0.5) node[right] {$D$};
\draw[red] (0.5,0.5) -- (5,5) node[right] {$S$};
% 均衡点与虚线投影
\coordinate (E) at (2.75,2.75);
\fill (E) circle (2pt) node[above right] {$E$};
\draw[dashed] (E) -- (E|-0,0) node[below] {$Q^*$};
\draw[dashed] (E) -- (E-|0,0) node[left] {$P^*$};
\end{tikzpicture}
编译出来就是这样(矢量,放大不糊、字体随正文):
要表现“需求外移”,再画一条平移的虚线并加箭头即可:
\draw[blue, dashed] (1.5,5) -- (6,0.5) node[right] {$D'$};
\draw[->] (3.2,2.8) -- (3.9,3.5); % 移动方向箭头
\coordinate 命名关键点、(E|-0,0) 这种语法做垂直/水平投影——这是 TikZ 画经济图最省事的两个技巧,福利三角形、税收楔子都靠它们拼。
二、博弈树(扩展式)
博弈树用 forest 宏包最省心(\usepackage{forest}),它专门画树:缩进表示父子,方括号嵌套,叶子放收益。
\begin{forest}
for tree={s sep=24mm, l=18mm, edge={-}}
[$1$
[$2$, edge label={node[midway,left]{$L$}}
[{$(2,1)$}, edge label={node[midway,left]{$\ell$}}]
[{$(0,0)$}, edge label={node[midway,right]{$r$}}]
]
[{$(1,2)$}, edge label={node[midway,right]{$R$}}]
]
\end{forest}
$1$、$2$ 是轮到谁行动的决策结,分支上的 L/R/ℓ/r 是行动,叶子 (2,1) 是收益向量。生成出来:
要标信息集(虚线连两个不可区分的结),在 forest 里给两个结命名再 \draw[dashed] 连起来即可——一图胜过几段文字解释贝叶斯纳什。
三、识别设计的时间线
写 DID / 事件研究 / RDD 的论文,正文配一条时间线说清“谁在什么时候被处理、对照组是谁”,审稿人理解成本骤降。一根带刻度的箭头就够:
\begin{tikzpicture}[>=Stealth]
\draw[->, thick] (0,0) -- (10,0);
\foreach \x/\t in {1/2018, 3/2019, 5/2020, 7/2021, 9/2022}
\draw (\x,0.12) -- (\x,-0.12) node[below] {\t};
% 处理时点
\draw[red, thick, dashed] (5,-0.6) -- (5,1);
\node[red, align=center] at (5,1.35) {政策实施\\$t=0$};
\node[align=center] at (2,0.9) {处理前\\(建立基期)};
\node[align=center] at (8,0.9) {处理后\\(估计动态效应)};
\end{tikzpicture}
\foreach 批量打刻度是这里的关键——加一年改一处,不用一个个挪坐标。
四、带数据的散点 + 回归线(pgfplots)
前三张是纯示意图,但你也会想直接在 LaTeX 里画带数据的散点和拟合线,省去 Stata / R 出图再插回来的来回。这时候用 pgfplots——TikZ 上的一层,专门管坐标系和数据。
\documentclass[tikz,border=4pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
width=8cm, height=6cm,
xlabel={$\log(\text{人均 GDP})$},
ylabel={平均受教育年限},
xmin=6, xmax=12, ymin=0, ymax=15,
grid=both, grid style={gray!20},
legend pos=south east,
]
% 散点
\addplot[only marks, mark=*, mark size=1.4pt, color=blue!70]
table[x=lgdp, y=edu] {data.dat};
% OLS 拟合线
\addplot[red, thick, domain=6:12] {1.2*x - 4.5};
\legend{各国数据, OLS 拟合}
\end{axis}
\end{tikzpicture}
\end{document}
data.dat 是空格/tab 分隔的纯文本,第一行是列名(lgdp edu),Stata 的 outsheet 或 R 的 write.table 一行命令就能出。这样写出来的图——
- 字体和论文一致(不像 Stata 默认导出的 PNG/PDF 字体常错位);
- 样式可由
\pgfplotsset{...}全局控制——投到 AER 改一遍配色,所有图同步换; - 可编程:
\foreach \i in {1,...,5}批量画 5 个子图 /\addplot expression直接画回归线表达式,省得自己算坐标。
进阶用法(在论文里很值钱的几个):
axis cs:锚点 +\node可以在数据坐标系里加注释(“政策实施 →” 指向某个点);- 双 y 轴(一边失业率一边 GDP 增速)用
\begin{axis}套\begin{axis}[axis y line*=right]; - 95% 置信带:
\addplot[name path=...]上下界,\addplot[fill=red, opacity=0.2] fill between[of=upper and lower]; - 在 Stata/R 出图后还想统一字体的话——
tikzDevice(R)和tikzpictureStata 包能直接导出.tikz源码而不是 PDF/PNG,省一道翻译。
工作流提醒
- 每张图独立
standalone文件,正文\includegraphics{figs/sd.pdf};图的字号用相对单位,正文缩放后仍清晰。 - 图多、编译慢时,开 TikZ externalization(
\usetikzlibrary{external}+\tikzexternalize),没改过的图直接复用已编译的 PDF,正文编译从几十秒回到几秒——这条和「告别 LaTeX 文件海洋」那套整洁工作流是一对。 - 同一份 TikZ 代码,论文和 beamer slides 可以直接复用,配色和字体天然统一。
不用背命令。把这三段当模板存进 commands.tex 旁边的 figures/ 目录,下次要画改数据点就行——TikZ 的价值不是炫技,是让你的图和论文是同一套排版语言。