# Relative positioning of two axis environments

I am trying to position one axis environment centered below another one. However, using

\begin{axis}[name=axis2, below of=axis1.south, anchor=north]


does not work as intended, see image below. A similar attempt using the positioning library and

\begin{axis}[name=axis2, below=of axis1.south, anchor=north]


produces similar wrong results.

What am I missing here? Are the axis anchors somehow determined later and not available at the point where I declare axis2?

\documentclass{article}
\usepackage{tikz}
\usepackage{pgfplots}
\usetikzlibrary{positioning}

\begin{document}
\begin{tikzpicture}
\begin{axis}[name=axis1]
\addplot table[row sep=crcr] {0 0 \\ 1 1 \\};
\end{axis}

\begin{axis}[name=axis2, below of=axis1.south, anchor=north]
\addplot table[row sep=crcr] {0 1 \\ 1 0 \\};
\end{axis}
\end{tikzpicture}
\end{document}


• Apparently, just using anchor = north west solves the problem. However, I can't explain why yet. – KersouMan Nov 14 at 14:27
• @KersouMan yes, but when I set a distance between the two plots using positioning, it breaks again. I would be interested to learn what the reason is... – wimi Nov 14 at 14:33
• The axis environment may act like a node (more or less), but it isn't one. That [below of=...] works at all (even with bugs) is surprising. – John Kormylo Nov 14 at 15:08

Some objects like pics or axis objects only know their dimensions and anchor positions "too late". A very simple trick to position those is to wrap them in a basic matrix (which does not require the matrix library).

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16} %<- you may want to add this
\usetikzlibrary{positioning}

\begin{document}
\begin{tikzpicture}
\matrix{
\begin{axis}[name=axis1]
\addplot table[row sep=crcr] {0 0 \\ 1 1 \\};
\end{axis}\\[1em]

\begin{axis}[name=axis2]
\addplot table[row sep=crcr] {0 1 \\ 1 0 \\};
\end{axis}\\
};
\end{tikzpicture}

\begin{tikzpicture}
\matrix(axis1){
\begin{axis}
\addplot table[row sep=crcr] {0 0 \\ 1 1 \\};
\end{axis}\\};
\matrix[below=1cm of axis1](axis2){
\begin{axis}
\addplot table[row sep=crcr] {0 1 \\ 1 0 \\};
\end{axis}\\
};
\end{tikzpicture}

\end{document}


For just stacking the plots, it suffices to put them in one matrix.

If you wish to access all the features of positioning, put each axis in an individual matrix.

If you change the code for the second axis to become

 \matrix[below=1cm of axis1.south east](axis2){...


you get

as expected.

I continue debating with myself whether it is worthwhile to copy the relevant parts of the matrix definition (notice that this is the core stuff contained in the pgf module matrix, not in the library of the same name!) to define a wrapper that allows one to use positioning on pic and other objects like axis more easily, but the above is already very simple, so I hesitate.

If you are not strict about using positioning library, you can go for using scope.

\documentclass{article}
\usepackage{pgfplots}

\begin{document}
\begin{center}
\begin{tikzpicture}
\begin{scope}
\begin{axis}
\addplot table[row sep=crcr] {0 0 \\ 1 1 \\};
\end{axis}
\end{scope}

\begin{scope}[yshift=-7cm]
\begin{axis}
\addplot table[row sep=crcr] {0 1 \\ 1 0 \\};
\end{axis}
\end{scope}
\end{tikzpicture}
\end{center}
\end{document}


The default is to located the lower left corner (anchor=south west) at the origin. One can apply shift directly to the axis to move it.

\documentclass{article}
\usepackage{tikz}
\usepackage{pgfplots}
\usetikzlibrary{positioning}

\begin{document}
\begin{tikzpicture}
\begin{axis}[name=axis1]
\addplot table[row sep=crcr] {0 0 \\ 1 1 \\};
\end{axis}

%\coordinate[below of=axis1.south] (test);% does not work
\path (axis1.south) ++ (0,-1cm) coordinate (test);

\begin{axis}[name=axis2, anchor=north, shift=(test)]
\addplot table[row sep=crcr] {0 1 \\ 1 0 \\};
\end{axis}

\draw[red] (0,0) -- (axis1.south);
\draw[green] (0,0) -- (axis2.north);

\end{tikzpicture}
\end{document}


Just for fun, this shows how to use the local bounding box around the first axis to position the lower axis.

\documentclass{article}
\usepackage{tikz}
\usepackage{pgfplots}
\usetikzlibrary{positioning}

\begin{document}
\begin{tikzpicture}
\begin{scope}[local bounding box=outer]
\begin{axis}[name=axis1]
\addplot table[row sep=crcr] {0 0 \\ 1 1 \\};
\end{axis}
\end{scope}

\draw[red] (outer.south west) rectangle (outer.north east);
\path (axis1.south |- outer.south) ++ (0,-.333em) coordinate (test);

\begin{axis}[name=axis2, anchor=north, shift=(test)]
\addplot table[row sep=crcr] {0 1 \\ 1 0 \\};
\end{axis}

\end{tikzpicture}
\end{document}


And here two other possibilities to position axis environments relative to each other.

1. Using the at key and
2. using the groupplots library

Both can be found in the PGFPlots manual. For details please have a look at the comments in the code.

% used PGFPlots v1.16
\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}
% used for the second possibility
\usepgfplotslibrary{groupplots}
% common options
\pgfplotsset{
table/row sep=crcr,
}
\begin{document}
% first possibility
\begin{tikzpicture}
\begin{axis}[
title={first possibility},
xlabel=x label,
% name the first axis environment
name=axis1,
]
\addplot table {0 0 \\ 1 1 \\};
\end{axis}

\begin{axis}[
% position the second axis using at ...
at={(axis1.below south west)},
% ... and add a proper anchor
anchor=north west,
% optionally/additionally a yshift can be stated
yshift=-5mm,
ylabel=y label,
]
\addplot table {0 1 \\ 1 0 \\};
\end{axis}
\end{tikzpicture}

\hspace{1cm}

% second possibility
\begin{tikzpicture}
% use the groupplots library and the groupplot environment
\begin{groupplot}[
group style={
% state the alignment of the plots (<horizontal> by <vertical>)
group size=1 by 2,
% optionally state the vertical separation
vertical sep=15mm,
},
]
\nextgroupplot[
title={second possibility},
xlabel=x label,
]
\addplot table {0 0 \\ 1 1 \\};
\nextgroupplot[
ylabel=y label,
]
\addplot table {0 1 \\ 1 0 \\};
\end{groupplot}
\end{tikzpicture}
\end{document}