5

This question already has an answer here:

Many times, it happens to me to produce stacked time history plots, with xticks and xlabel in common in order to save vertical space in papers.

Consider the following MWE:

\documentclass{standalone}
\usepackage{pgfplots}

\pgfplotsset{
  compat=1.14, 
  width=200pt,
  height=100pt,
}

\begin{document}

  \begin{tikzpicture}
    \begin{axis}[
      name = plot1,
      xticklabels={,,},
      ylabel = {$x_1$},
      xmajorgrids,
    ]
      \addplot coordinates {(1,0.0001)(2,0.0002)(3,0.0003)};
    \end{axis}

    \begin{axis}[
      at=(plot1.south west), anchor=north west,
      xlabel = {$t$[s]},
      ylabel = {$x_2$},
      xmajorgrids,
    ]
      \addplot coordinates {(1,0.0002)(2,0.0004)(3,0.0006)};
    \end{axis}

  \end{tikzpicture}%
\end{document}

which produces the following result:

enter image description here

As one can notice, the y-axis multiplier position is a problem. A possible solution would be specify the multiplier in every y tick label with scaled y ticks=false, but then the result is really heavy and space consuming.

I would like to be able to pragmatically produce the following result:

enter image description here

which, in my opinion, is really compact and elegant.

To do this programmatically, the exponent of the scientific notation is needed, in order to put it in the ylabel, something like:

ylabel = {$x_1 \cdot 10^{-\sci_exponent}$},

and then a way to get the scaled ytick label.

Is it possible?

Please, note that, differently from Automatically put PGFPlots xtick scale label in x axis label, I do not want just move the exponent, but I would like to invert the exponent in order to (for example) get $10^{4} in place of 10^{-4}, as in the figures above.

marked as duplicate by Zarko tikz-pgf Feb 4 '17 at 21:25

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • I seem to remember that this question, or one very similar, has been asked before sometime. I couldn't find it at the moment, and I'm not even sure if it was answered, but some more searching might be fruitful. – Torbjørn T. Jan 30 '17 at 11:06
2

Working on the solution proposed in Automatically put PGFPlots xtick scale label in x axis label, I came up with this totally automatic solution (even if a bit dirty):

\documentclass{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.14}

\begin{document}

    \begin{tikzpicture}
    \begin{axis}[
        xtick scale label code/.code={\pgfmathparse{int(-#1)}$x \cdot 10^{\pgfmathresult}$},
        every x tick scale label/.style={at={(xticklabel cs:0.5)}, anchor = north},
        ytick scale label code/.code={\pgfmathparse{int(-#1)}$y \cdot 10^{\pgfmathresult}$},
        every y tick scale label/.style={at={(yticklabel cs:0.5)}, anchor = south, rotate = 90},
    ]

    \addplot coordinates { (0.0001,0.001)(0.0002,0.002)(0.0003,0.003) };

    \end{axis}
    \end{tikzpicture}

\end{document}

which produce the following output:

enter image description here

and automatically adapts to the data order of magnitude.

1

As Torbjørn T. already stated in the comment below the question there was a similar question a while ago: Automatically put PGFPlots xtick scale label in x axis label. But I don't like the solution presented there by Budo Zindovic, because this has several side effects which I don't want to mention here.

Therefore I present another solution. For more details on how it works, please have a look the comments in the code.

(Just as additional information:
I already asked Christian Feuersänger (the author of PGFPlots), if there is a possibility to only access the "scale value", but didn't get an answer so far. This would allow a much more automated solution than this one. If anybody already has an idea, I'd be very happy to know that.)

\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}
    % I think it is easier to use the `groupplots' library for your purpose
    % and in case you would have the "multipliers" in the *unit part* then
    % this would be very easy with the `units' library
    \usetikzlibrary{
        pgfplots.groupplots,
        pgfplots.units,
    }
    \pgfplotsset{
        % use this `compat' level or higher to use the improved positioning of axis labels
        compat=1.3,
        width=200pt,
        height=100pt,
        % state that we want to use the features of the `units' library
        use units=true,
        % what style do we want to use to show the units?
        unit markings=slash space,  % other options: parenthesis, square brackets
    }
% use the `siunitx' package to state (numbers and) units
\usepackage{siunitx}
\begin{document}
    \begin{tikzpicture}
            % to be consistent with the factoring, define the scaling factor here
            \def\Factor{4}
        \begin{groupplot}[
            group style={
                % we have 1 column with 2 rows of plots
                group size=1 by 2,
                % make the vertical sep a bit smaller than the default
                vertical sep=2ex,
                % we want to show the ticks and labels only at the plot at the bottom
                x descriptions at=edge bottom,
            },
            % set the xlabel and the corresponding unit; the later with the help of the
            % `siunitx' package
            xlabel= {$t$},
            x unit={\si{\second}},
            xmajorgrids,
            %%% change the scaling of the data
            % this is done automatically,
            % but to be consistent we provide it "manually" using the above defined variable
            scaled y ticks=base 10:\Factor,
            % but we don't want to show the label (here)
            ytick scale label code/.code={},
%            % both previous can be given manually with the following key
%            % (the both arguments correspond to the previous ones in reverse order)
%            scaled y ticks=manual:{}{\pgfmathparse{#1*1e\Factor}},
            %
            % to not have to add the "multiplier" to each `ylabel' apply it as
            % prefix to all
            execute at end axis={
                % (the `pgfplotsset' is necessary, because `execute at end axis'
                % only executes *executable* code and `ylabel/.add' is no executable code.)
                \pgfplotsset{
                    ylabel/.add={\num{e\Factor}\,}{},
                }
            },
        ]
        \nextgroupplot[
            % (as it seems this has to be done at every `\nextgroupplot' manually:)
            % add the "multiplier" to each `ylabel'
            % of course also here we use the defined factor to be consistent between the
            % "automatic" scaling and the factor in the label
            ylabel={$x_1$},
        ]
            \addplot coordinates { (1,0.0001)(2,0.0002)(3,0.0003) };
        \nextgroupplot[
            ylabel={$x_2$},
        ]
            \addplot coordinates { (1,0.0002)(2,0.0004)(3,0.0006) };
        \end{groupplot}
    \end{tikzpicture}
\end{document}

image showing the result of above code

  • Thank you for your answer. It contains a lot of interesting tricks, even if not really on topic. The main drawback is that, as I undertand from your answer, so far there is no possibility to access the "scale value". I'm sorry, but in your solution (like in the code I used to produce the bottom plot in my question) the "scale value" in the ylabel is hard coded, which is what I would like to avoid, since it may lead to mistakes in case of data loaded from a file. – mrk_brn Jan 31 '17 at 10:46
  • That is true, a lot of the solution is not topic related, but shows a "better" solution in general (as I think). And you are right, my solution is not fully automatic, but I edited so at least the result is always consistent regarding the factoring and the label by introducing a defined variable \Factor which used. – Stefan Pinnow Jan 31 '17 at 19:34

Not the answer you're looking for? Browse other questions tagged or ask your own question.