Causal Graphs in LaTex

Because powerpoint graphs suck.

August 15, 2018

When starting my research in causality, I did not know how to draw causal models. Most people I asked drew their graphs in powerpoint or some other software, and then exported them as png.

Drawing the graphs from scratch was tedious, and they often ended up looking fairly amateurish. To combat this, a couple years ago, I created a web-based app to draw graphs and export them to png, which is available here.

The exported pngs were easy to make, but there was the issue of needing to align nodes each time I needed to make a change, and the resulting graphs were passable, but did not look beautiful.

Since then, members of our group and I have figured out how to make these graphs directly in latex, and I think they look really great.

This post serves as an example-based intro to causal graphs in tikz.

The Basics

Here is a full template document with a tikz graph. The graph is called the “bow graph”, and it represents a causal effect with latent confounding.

\documentclass[10pt]{article}
\usepackage{color}
\usepackage{tikz}

% Tikz settings optimized for causal graphs.
% Just copy-paste this part
\usetikzlibrary{shapes,decorations,arrows,calc,arrows.meta,fit,positioning}
\tikzset{
-Latex,auto,node distance =1 cm and 1 cm,semithick,
state/.style ={ellipse, draw, minimum width = 0.7 cm},
point/.style = {circle, draw, inner sep=0.04cm,fill,node contents={}},
bidirected/.style={Latex-Latex,dashed},
el/.style = {inner sep=2pt, align=left, sloped}
}
\begin{document}

\begin{tikzpicture}
% x node set with absolute coordinates
\node[state] (x) at (0,0) {$X$};

% y node set relative to x.
% Locations can be:
% right,left,above,below,
% above left,below right, etc
\node[state] (y) [right =of x] {$Y$};

% Directed edge
\path (x) edge (y);

% Bidirected edge
\path[bidirected] (x) edge[bend left=60] (y);
\end{tikzpicture}
\end{document}
Download

The majority of the above code can be simply copy-pasted into your own tex file without modification. The only thing that you need to change for your own graphs is within the tikzpicture.

You might have noticed that the output of the given code is a pdf, while the graph shown above is an svg. You can use \documentclass{standalone} and pdf2svg to generate a high-quality svg of your graph. The actual code used for the above graph is given here, and the image can be generated on linux using:

pdflatex -shell-escape templatesvg.tex

All the below graphs assume to have the same tikz settings as shown in the template above, with just the tikzpicture portion replaced.

Dot Nodes

More complex graphs can look better if they use dots for their nodes, with labels to the side:

\begin{tikzpicture}
\node (x) at (0,0) [label=left:X,point];
\node (y) at (1.3,0) [label=right:Y,point];

\path (x) edge (y);
\path[bidirected] (x) edge[bend left=60] (y);
\end{tikzpicture}
Download

The label directions are same as for node positioning. The label text can have spaces in it:

\node (x) at (0,0) [label=above left:This is a valid label,point];

Coloring Nodes and Edges

\begin{tikzpicture}
\node[state,red] (x) at (0,0) {$X$};
\node[state] (y) [right=of x] {$Y$};

\path (x) edge (y);
\path[blue,line width=1.5] (x) edge[bend right=30] (y);
\path[bidirected] (x) edge[bend left=60] (y);
\end{tikzpicture}
Download

Labeling Edges

\begin{tikzpicture}
\node[state] (1) {$Z$};
\node[state] (2) [right =of 1] {$X$};
\node[state] (3) [right =of 2] {$Y$};
\node[state] (4) [above right =of 1,xshift=-0.3cm,yshift=-0.3cm] {$W$};

\path (1) edge node[above] {$\lambda_{zx}$} (2);
\path (2) edge node[above] {$\lambda_{xy}$} (3);
\path[bidirected] (2) edge[bend left=60] node[above] {$\epsilon_{xy}$} (3);
\path (4) edge node[el,above] {$\lambda_{wz}$} (1);
\path[bidirected] (4) edge[bend left=50] node[el,above] {$\epsilon_{wy}$} (3);
\end{tikzpicture}
Download

Text Nodes

\begin{tikzpicture}
\node (1) at (0,0) {Proximity};
\node (2) [right = of 1] {Tutoring};
\node (3) [right = of 2] {GPA};
\node (4) [below = of 2] {Library};

\path (1) edge (2);
\path (2) edge (3);
\path[bidirected] (2) edge[bend left=50] (3);
\path (4) edge (3);
\path (1) edge (4);
\end{tikzpicture}
Download

Boxed

\begin{tikzpicture}
\node[state] (p) at (0,2) {$S$};
\node[state,rectangle] (k) at (-1.5,1) {$K$};
\node[state] (x) at (0,0) {$L$};
\node[state] (y) at (1.5,0) {$M$};

\path (x) edge (y);
\path (p) edge (k);
\path[bidirected] (p) edge[bend left=20] (y);
\path[bidirected] (p) edge[bend left=20] (x);
\path[bidirected] (k) edge[bend left=20] (y);
\path (k) edge (x);

\node[draw=blue,dotted,fit=(x) (y), inner sep=0.2cm] (machine) {};
\end{tikzpicture}
Download

A Pretty Graph

This example, courtesy of Carlos Cinelli from Judea Pearl’s group, really goes to show how nice these graphs can look.

\begin{tikzpicture}[node distance =0.85 cm and 0.85 cm]
\node (z) [label = below:z, point];
\node (w) [above = of z,yshift=0.3cm, label = above:w, point];
\node (x) [label = below:x, below left = of z, point];
\node (y) [label = below:y, point, below right = of z];

\path (z) edge node[above, el] {$\lambda_{zw}$} (w);
\path (z) edge node[above, el] {$\lambda_{zx}$} (x);
\path (x) edge node[below] {$\lambda_{xy}$} (y);

\path[bidirected] (z) edge[bend left= 60] node[above, el] {$\epsilon_{zy}$} (y);
\path[bidirected] (z) edge[bend right=60] node[above, el] {$\epsilon_{zx}$} (x);
\path[bidirected] (z) edge[bend left= 60] node[above, el] {$\epsilon_{zw}$} (w);
\path[bidirected] (w) edge[bend left= 60] node[above, el] {$\epsilon_{wy}$} (y);
\end{tikzpicture}
Download


References

  1. LaTeX/PGF/TikZ - Wikibooks, Open Books for an Open World. (n.d.). Retrieved August 15, 2018, from en.wikibooks.org
  2. Graphics - How Do I Label These Dots in Tikz Image? (n.d.). Retrieved August 15, 2018, from tex.stackexchange.com
  3. Graph Drawing - Tikz: Draw Edge from Node to Label of Another Edge. (n.d.). Retrieved August 15, 2018, from stackoverflow.com
  4. Node Shapes | TikZ Example. (n.d.). Retrieved August 15, 2018, from www.texample.net
  5. Positioning of Label Edge (Tikz Figure). (n.d.). Retrieved August 15, 2018, from tex.stackexchange.com