pgfplots, obtenha o expoente do eixo em notação científica

pgfplots, obtenha o expoente do eixo em notação científica

Muitas vezes me acontece produzir gráficos de história temporal empilhados, com xtickse xlabelem comum, para economizar espaço vertical nos papéis.

Considere o seguinte 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}

que produz o seguinte resultado:

insira a descrição da imagem aqui

Como se pode notar, a posição do multiplicador do eixo y é um problema. Uma solução possível seria especificar o multiplicador em cada rótulo de y tick com scaled y ticks=false, mas o resultado é muito pesado e consome espaço.

Eu gostaria de poder produzir pragmaticamente o seguinte resultado:

insira a descrição da imagem aqui

que, na minha opinião, é muito compacto e elegante.

Para fazer isso programaticamente, é necessário o expoente da notação científica, para colocá-lo no ylabel, algo como:

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

e, em seguida, uma maneira de obter o rótulo ytick em escala.

É possível?

Por favor, note que, diferentemente deColocar automaticamente o rótulo da escala xtick do PGFPlots no rótulo do eixo x, não quero apenas mover o expoente, mas gostaria de inverter o expoente para (por exemplo) ocupar o $10^{4}lugar de 10^{-4}, como nas figuras acima.

Responder1

Trabalhando na solução proposta emColocar automaticamente o rótulo da escala xtick do PGFPlots no rótulo do eixo x, criei esta solução totalmente automática (mesmo que um pouco suja):

\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}

que produzem a seguinte saída:

insira a descrição da imagem aqui

e se adapta automaticamente à ordem de grandeza dos dados.

Responder2

ComoTorbjorn T.já declarado no comentário abaixo da pergunta, houve uma pergunta semelhante há algum tempo:Colocar automaticamente o rótulo da escala xtick do PGFPlots no rótulo do eixo x. Mas não gosto da solução apresentada ali porBudo Zindovic, porque isso tem vários efeitos colaterais que não quero mencionar aqui.

Portanto apresento outra solução. Para mais detalhes sobre como funciona, dê uma olhada nos comentários no código.

(Apenas como informação adicional:
já perguntei a Christian Feuersänger (autor do PGFPlots), se existe a possibilidade de aceder apenas ao "valor da escala", mas não obtive resposta até agora. Isto permitiria uma solução muito mais automatizada do que este. Se alguém já tiver uma ideia, ficaria muito feliz em saber disso.)

\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}

imagem mostrando o resultado do código acima

informação relacionada