# Use tikz to draw a hierarchical model (mult-level model from statistics)

I am trying to draw a representation of a statistical multi-level model: examples of what I am trying to do can be seen in figures 3a or 3b, at http://www.esourceresearch.org/tabid/332/Default.aspx.

I have made an attempt, but cannot get the spacing correct. In the figure below, the children of c1 and cn overlap (so that only the child of cn can be seen). I also do not know how to appropriately add the dots between each of the levels: between one and two and two and n, and between t1 and tn, and so on. I tried just adding an extra child node, but I from the looks of it, it is not the way to go. Thanks.

My code

\documentclass{article}
\usepackage[landscape, left=10pt]{geometry}
\usepackage{tikz}
\begin{document}

% styles
\tikzstyle{every node} = [rectangle, draw,  text centered, rounded corners, fill=blue!20, minimum height=1cm, minimum width=1cm]

\begin{tikzpicture}[sibling distance=1.25cm]

\node { one }
child { node {c1}
child { node {t1}}
child { node [draw=none] {\ldots}}
child { node {tn}}
}
child { node [draw=none] {\ldots}
}
child { node {cn}
child { node {t1}}
child { node [draw=none] {\ldots}}
child { node {tn}}
}
;

\hspace*{7cm} \node { two }
child { node {c1}
child { node {t1}}
child { node [draw=none] {\ldots}}
child { node {tn}}
}
child { node [draw=none] {\ldots}
}
child { node {cn}
child { node {t1}}
child { node [draw=none] {\ldots}}
child { node {tn}}
};

\hspace*{7cm} \node { n }
child { node {c1}
child { node {t1}}
child { node [draw=none] {\ldots}}
child { node {tn}}
}
child { node [draw=none] {\ldots}
}
child { node {cn}
child { node {t1}}
child { node [draw=none] {\ldots}}
child { node {tn}}
};

\end{tikzpicture}

\end{document}


May I recommend the specialist tree-drawing package, Forest?

\documentclass[border=10pt,multi,tikz]{standalone}
\usepackage{forest}
\begin{document}

\begin{forest}
for tree={
math content,
},
delay={
where content={}{
if level=0{}{
content=\ldots,
math content,
no edge,
fit=band,
},
}{
rounded corners,
outer color=blue!20,
inner color=blue!15,
minimum height=1cm,
minimum width=1cm,
draw,
},
}
[, phantom
[one, plain content
[c_1
[t_1]
[]
[t_n]
]
[]
[c_n
[t_1]
[]
[t_n]
]
]
[two, plain content
[c_1
[t_1]
[]
[t_n]
]
[]
[c_n
[t_1]
[]
[t_n]
]
]
[]
[n
[c_1
[t_1]
[]
[t_n]
]
[]
[c_n
[t_1]
[]
[t_n]
]
]
]
\end{forest}

\end{document}


# EDIT

Here's a fancier version which defines label levels as a style for trees which should have level labels. Labels should be added within the tree using level label=<label text> and will be concatenated to form a label for that level, preceded by the prefix Label <level number>. All of this can be adjusted, of course.

I've also added a fancier background, but that's obviously strictly optional.

\documentclass[border=10pt,multi,tikz]{standalone}
\usepackage{forest}
\forestset{
declare toks={level label}{},
declare toks register={level labels},
level labels={},
declare count register={leveller},
leveller'=0,
level split/.style={
temptoksa={#1},
split register={temptoksa}{:}{tempcounta,level label split},
},
level label split/.style={
temptoksb={#1},
temptoksc={},
split register={temptoksb}{,}{temptoksc, level label splitter},
tikz+/.wrap 2 pgfmath args={
\node (label leveller ##1) [anchor=east, align=right, font=\sffamily] at (level ##1.west -| westpoint) {##2};
}{tempcounta}{temptoksc},
before computing xy/.wrap pgfmath arg={
tikz+={
\node [anchor=north east, align=right, font=\sffamily\itshape] at (label leveller ##1.north -| west of westpoint) {Level ##1};
},
}{tempcounta},
},
level label splitter/.style={
temptoksc+={\\#1},
},
label levels/.style={
tikz+={
\coordinate (westpoint) at ([xshift=-15pt]current bounding box.west);
},
before packing={
tikz+={
\coordinate (west of westpoint) at ([xshift=-15pt]current bounding box.west);
},
},
before drawing tree={
tikz+={
\scoped[on background layer]{\node [left color=blue!50!cyan!25!white, right color=blue!50!cyan!25!white, middle color=blue!50!cyan, inner sep=10pt, rounded corners, draw=blue!50!cyan, draw opacity=.5, fill opacity=.15, fit=(current bounding box)] {};}
},
},
delay={
if level label={}{}{
if={(level())>(leveller)}{
leveller/.option=level,
alias/.wrap pgfmath arg={level ##1}{level()},
if level labels={}{}{
level labels+={;},
},
level labels+/.option=level,
level labels+={:},
}{},
level labels+/.option=level label,
level labels+={,},
},
},
},
before typesetting nodes={
if level labels={}{}{
split register={level labels}{;}{level split},
},
},
}
}
\begin{document}

\begin{forest}
for tree={
math content,
},
delay={
where content={}{
if level=0{}{
content=\ldots,
math content,
no edge,
fit=band,
},
}{
rounded corners,
outer color=blue!20,
inner color=blue!15,
minimum height=1cm,
minimum width=1cm,
draw,
},
},
label levels,
[, phantom
[one, plain content, level label=platitudes
[c_1
[t_1]
[]
[t_n]
]
[]
[c_n
[t_1]
[]
[t_n]
]
]
[two, plain content
[c_1
[t_1, level label=latitudes]
[]
[t_n]
]
[]
[c_n
[t_1]
[]
[t_n, level label=longitudes]
]
]
[]
[n
[c_1, level label=magnitudes
[t_1]
[]
[t_n]
]
[]
[c_n
[t_1]
[]
[t_n]
]
]
]
\end{forest}

\end{document}


• If you want the level labels at the left, let me know. justtrees can do this straightforwardly and I need stuff to test it on. Or I can just show you how to do it a little less straightforwardly without justtrees ;).
– cfr
Oct 11 '16 at 16:02
• that looks great, thank you. I had actually noticed a few of your previous posts usingforest but hadn't managed to produce anything reasonable. If there is a way to adapt this to add labels on the left that would be great, but as is im very happy. Oct 11 '16 at 16:41
• @user20650 Please see edit above. Forest takes some getting used to, but it is really nice and well worth the effort.
– cfr
Oct 11 '16 at 23:18
• That looks really great. Thank you so much. As I mentioned above, I had seen your previous forest answers, but I had found the syntax a little to grasp. But im convinced, to make an effort. Is the ctan.org/pkg/forest guide best place to start? Oct 11 '16 at 23:39
• @user20650 Yes. For a simple introduction to the syntax, you might try this answer of mine: tex.stackexchange.com/questions/5447/…. The question is not about Forest, so it doesn't have the forest tag, but I try to give a very basic intro to Forest in the answer.
– cfr
Oct 11 '16 at 23:56