# Aligning subplots in a pgfplots figure

I have the following figure (a very, very stripped down version of a figure I created using matlab2tikz)

My problem is that the subplots are not aligned correctly due to the fact that the y axis labels for the 2nd and 4th subplots (the ones on the second column) have different widths. The code for this MWE is

\documentclass{standalone}
\usepackage{pgfplots, tikz}
\pgfkeys{/pgf/number format/.cd,fixed,precision=3}
\pgfplotsset{
compat=1.3,
every axis/.append style={scale only axis, axis on top,
height=4.25cm, width=4.5cm, xmin=-1, xmax=240,
}
}

\begin{document}
\begin{tikzpicture}

\begin{axis}[%
name=plot1,
ymin=-0.5, ymax=0]
\end{axis}

\begin{axis}[%
name=plot2,
at=(plot1.right of south east), anchor=left of south west,
ymin=-6.5, ymax=0.2]
\end{axis}

\begin{axis}[%
name=plot4,
at=(plot2.below south west), anchor=above north west,
ymin=-1.2, ymax=0]
\end{axis}

\begin{axis}[%
name=plot3,
at=(plot4.left of south west), anchor=right of south east,
ymin=-1, ymax=0]
\end{axis}

\end{tikzpicture}
\end{document}


I have thought about this and I have found three ways to get the plots to be aligned:

1. I could insert invisible things in the y-axis labelling for the second subplot, making it as wide as the y-axis of the fourth subplot, by adding two lines to the second axis:

\begin{axis}[%
name=plot2,
at=(plot1.right of south east), anchor=left of south west,
ymin=-6.5, ymax=0.2,
ytick={-6,-4,-2,0},
yticklabels={{\color{white} 0.}$-6$,$-4$,$-2$,$0$} ]
\end{axis}

2. Instead of defining the subplots and their positioning in the order 1 -> 2 -> 4 -> 3, I could do it as 1-> 3 -> 4 -> 2. That would entail changing the order in which the axes are defined, but also the lines defining positioning. The full code can be seen here, but the lines of interest in the order in which they appear would be

name=plot1,

name=plot3,
at=(plot1.below south east), anchor=above north east,

name=plot4,
at=(plot3.right of north east), anchor=left of north west,

name=plot2,
at=(plot4.above north west), anchor=below south west,

3. I could force all numbers to have one decimal point (and hence all the y labelling to have the same width) by changing the line (the third in the code)

\pgfkeys{/pgf/number format/.cd,fixed,precision=3}


to

    \pgfkeys{/pgf/number format/.cd,fixed,fixed zerofill,precision=1}


I like the results from solutions 1 and 2, which produce identical figures like this

but the way it is implemented is flawed and might be difficult to apply when there are more than 4 subplots (plus solution 2 might not even work!).

I like the way the 3rd solution is implemented: a global setting which makes it all work, but I really don't like the final result (those .0 are really ugly!):

My question is then: how can I solve this optimally? Is there a global setting I can apply which would force all the subplots to be aligned without having to resort to invisible writings, fake decimal points or changing the order the plots are defined?

-
Adding the option xshift=3mm to the plot2 axis options seems to solve the problem. –  percusse Nov 29 '11 at 0:36
@percusse (2.8 to be more precise!). I would appreciate if you put this as an answer, because if I can't find some global solution which fixes it all, your way is better than any of the ones I proposed. And you definitely deserve rep points :) –  Vivi Nov 29 '11 at 0:49
I really feel like positioning library should be able to handle it or some \phantom{0} space for the missing decimal space, I'll let you know if I think of something less uglier :) –  percusse Nov 29 '11 at 0:56
Great! I spent quite some time on it and the 3 above were the best I came up with, but you already gave me a better solution :) –  Vivi Nov 29 '11 at 0:58
I guess matrix environment is the next easiest fix. –  percusse Nov 29 '11 at 1:04

This is similar to the problem in PGFplot to occupy full \linewidth, and aligned y=axis across tikzpicture where Jake provides a solution that names each of the figures, and keeping them in the same tikzpicture and position them using anchor points.

However, the solution I prefer is to set the width required by the yticklabel:

\pgfplotsset{yticklabel style={text width=3em,align=right}}


If the x axis tick labels also vary in size, you will also need a similar setting to fix the width of those as well.

-
+1 Such simplicity. –  percusse Nov 29 '11 at 1:11
Well I wish I had thought of that myself, but it is @Jake that we have to thank for this at the question I referenced in the solution. So you should up vote his answer there. –  Peter Grill Nov 29 '11 at 1:17
And I swear I looked through pgfplots.pdf and even pgfplotstable.pdf and could not find a solution. Brilliant! –  Vivi Nov 29 '11 at 1:19
@PeterGrill I wouldn't have found an answer had you not seen Jake's answer in the other post. Plus, how would I know it applied to my case? So you definitely deserve credit (but I did upvote his answer there, too. Weird it had only 1 upvote!) –  Vivi Nov 29 '11 at 2:31

I see some further alternatives which have not been elaborated so far:

1. Simply place\begin{tikzpicture}...\end{tikzpicture} into a LaTeX table. This is straightforward; you would do the very same thing with \includegraphics. In addition to \includegraphics, the baseline feature of tikz allows simple yet effective vertical alignment. In addition, the trim left and trim right features allow simple yet effective horizontal alignment (see http://mirror.ctan.org/graphics/pgf/contrib/pgfplots/doc/latex/pgfplots/pgfplots.pdf , section Alignment, subsection "Alignment in Array form (subplots)").

2. Use a single picture which contains an array of axes, i.e. a pattern like \begin{tikzpicture} \matrix{ multiple axes }; \end{tikzpicture}. This allows considerably simpler alignment! Alas, it needs special handling for legend entries due to a weakness of \matrix. If you use the external library (which is recommended), it takes more time since the picture gets larger. This approach is quite the same as the approaches shown above -- but the \matrix of tikz aligns all of the axis in a fully automated way. See the link posted above for examples and details.

3. Use the groupplots library shipped with pgfplots. It is specialized on axes in array form with particular strength if the axes are closely related (for example if they share axis descriptions like xlabel or even tick labels). Note, however, that the other approaches are better when it comes to automatic handling of bounding boxes.

Personally, I have always used approach (1): I like it if I have single, separated pictures which can easily be copy-pasted to another document. In addition, this simplifies image externalization because each image can be writte to a separate .pdf (see the external lib shipped with pgfplots or the standalone package).

I also found it well-looking if the tick labels are on the outside of the page, i.e. that the left column uses the default setting and the right column uses yticklabel pos=right. Again, the link above shows examples. This approach easily allows to center the complete figure in the middle of the page, perhaps with tick labels in the page's margin and the axis' boxes aligned with the page's text width.

-

As a quick and dirty solution, adding the precise option xshift=2.8mm to the plot2 axis options seems to solve the problem :) But using a matrix environment solves the problem without referencing to the anchors:

\documentclass[article]
\usepackage{tikz,pgfplots}
\usetikzlibrary{matrix}
\pgfkeys{/pgf/number format/.cd,fixed,precision=3}
\pgfplotsset{
compat=1.3,
every axis/.append style={scale only axis, axis on top,
height=4.25cm, width=4.5cm, xmin=-1, xmax=240,
}
}
\begin{document}
\begin{tikzpicture}
\matrix{
\begin{axis}[%
name=plot1,
ymin=-0.5, ymax=0]
\end{axis}

&\begin{axis}[%
name=plot2,
ymin=-6.5, ymax=0.2]
\end{axis} \\

\begin{axis}[%
name=plot4,
ymin=-1.2, ymax=0]
\end{axis}

& \begin{axis}[%
name=plot3,
ymin=-1, ymax=0]
\end{axis}\\
};
\end{tikzpicture}
\end{document}

-
Cheers. If what I am after is not possible, I will accept your solution :) –  Vivi Nov 29 '11 at 0:54
you shouldn't delete regardless. It is a solution, even if there happens to be a better one. One day someone might be looking exactly for the effect the xshift gives and they will find it here! I am sure it will be useful for someone, and it was already useful for me. –  Vivi Nov 29 '11 at 1:05
Wonderful!! I quite like the matrix solution, though since the code is mostly auto-generated, the xshift is much easier to implement (less changes to be made). But I love it! –  Vivi Nov 29 '11 at 1:14
@Vivi I am also a power user of matlab and I recommend you to store all your data in a table format and later make pgfplots read and plot it, as explained by the manual. It takes some time to get comfortable with but saves a lot of time (pff, such a cliche, eh?) –  percusse Nov 29 '11 at 1:21
I will check it out. I think matlab2tikz is a great way to start, since most of it is done and you have time to learn by making small adjustments, but I believe I am ready to go to the next level :) Thanks again for your help, even though it wasn't the final answer I was after, I did learn heaps with it. –  Vivi Nov 29 '11 at 1:24