3

I'm trying to produce a boxplot with pgfplots where the data plotted is produced by some other command. Here a MCVE:

\documentclass{article}
 \usepackage{pgfplots}
 \pgfplotsset{compat=1.13}
 \usetikzlibrary{pgfplots.statistics}

 \newcommand{\addBoxplot}[1]{%
  \begin{tikzpicture}%
   \begin{axis}%
    \addplot[boxplot = {average = auto}] table[row sep=\\,y index=0] {#1};%
   \end{axis}%
  \end{tikzpicture}%
 }

 \newcommand{\getData}{data\\ 1\\ 3\\}

\begin{document}
 % Try 1
 \addBoxplot{data\\ 1\\ 3\\ }

 % Try 2
 \addBoxplot{\getData}
\end{document}

Try 1 demonstrates that the \addBoxplot command works as expected. Try 2 is the case I really am interested in. This produces an empty boxplot instead of giving just the same plot as try 1. Here is the output for me:

Output for me

The problem seems to be that the \getData is evaluated too late which causes \addBoxplot to produce the plot from invalid / empty data.

How can I implement \addBoxplot to work in context of try 2?

1 Answer 1

2

\expandafter can be your best friend (or your worst nightmare).

In this case, \addBoxplot doesn't want to see a macro name, it wants to see actual data, so the macro \getdata must be expanded once to so that \addBoxplot sees the argument in the form it likes.

\documentclass{article}
 \usepackage{pgfplots}
 \pgfplotsset{compat=1.13}
 \usetikzlibrary{pgfplots.statistics}

 \newcommand{\addBoxplot}[1]{%
  \begin{tikzpicture}%
   \begin{axis}%
    \addplot[boxplot = {average = auto}] table[row sep=\\,y index=0] {#1};%
   \end{axis}%
  \end{tikzpicture}%
 }

 \newcommand{\getData}{data\\ 1\\ 3\\}

\begin{document}
 % Try 1
 \addBoxplot{data\\ 1\\ 3\\ }

 % Try 2
 \expandafter\addBoxplot\expandafter{\getData}
\end{document}

enter image description here

5
  • Woohoo! This is the solution. Could you elaborate the mystery? I have tried \expandafter-variants before. Why do I need two of those?
    – m8mble
    May 17, 2017 at 12:51
  • I am also curious, I was trying the same, but I thought \expandafter would expand the second token encountered? May 17, 2017 at 12:52
  • @m8mble Think of it like reading left to right, this is the manner in which TeX digests the input. When getting to the 1st \expandafter, it momentarily skips \addBoxplot, and expands the 2nd instance of \expandafter, which says to skip the { and expand \getdata once. Having performed that much, it goes back and finds \addBoxPlot{data\\ 1\\ 3\\}. May 17, 2017 at 12:54
  • @PietroSaccardi See my prior comment. It gets really tricky if you want to expand something twice rather than once. Then you need groups of 3 \expandafters, as in \expandafter\expandafter\expandafter\addBoxplot\expandafter\expandafter\expandafter{\getData}. Can you see why? The 1st, 3rd, 4th, 6th instances will expand \getdata the 1st time, and then the 2nd,5th instances will expand it the 2nd time. Three expansions require 7 successive \expandafters using the same logic. May 17, 2017 at 12:58
  • 1
    @PietroSaccardi More specifically to your point, "I thought \expandafter would expand the second token encountered", the second token encountered is the {, not the \getData. May 17, 2017 at 13:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .