10

Update: Is there any possibility of drawing two box plots this way using a single datatable as in the updated MWE below?


I'm trying to use pgfplots 1.8's shiny new boxplot feature. As I am also showing the boxplot data in a table, I have the values pre-computed in R and written to an external file. So now I am trying to use the boxplot prepared with a data table rather than hard-coded values, but with very little effect.

My paltry first try at an MWE (taken nearly verbatim from section 5.9.1 Box Plots on p. 373 of the pgfmanual 1.8) is below. In essence, I was hoping to specify the column for the individual boxplot elements similar to the way you specify the x and y column when plotting a table (e.g. \addplot table[x=dof,y=L2] {datafile.dat};). However, I get a

! Package PGF Math Error: Unknown function 'lw' (in 'lw').

\documentclass[crop=false]{standalone}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.8}
\usepgfplotslibrary{statistics}
\begin{document}
\begin{tikzpicture}
\begin{axis}[boxplot/draw direction=y]
  \addplot+[
    boxplot prepared={
      lower whisker=lw,
      lower quartile=lq,
      median=med,
      upper quartile=uq,
      upper whisker=uw,
    },
  ]
  table[y index=0] {
    lw lq med  uq uw
     5  7 8.5 9.5 10
     4  5 6.5 8.5 9.5
  };
\end{axis}
\end{tikzpicture}
\end{document}

The hard-coded equivalent to this would be

\documentclass[crop=false]{standalone}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.8}
\usepgfplotslibrary{statistics}
\begin{document}
\begin{tikzpicture}
\begin{axis}[boxplot/draw direction=y]
  \addplot+[
    boxplot prepared={
      lower whisker=5,
      lower quartile=7,
      median=8.5,
      upper quartile=9.5,
      upper whisker=10,
    },
  ] coordinates{};
\end{axis}
\end{tikzpicture}
\end{document}

The coordinates{} is needed as pgfplots expects a list of outliers after the initial boxplot specification and baulks at an empty table{} statement.

0

1 Answer 1

18

The table in an \addplot command using the boxplot plot type is only used for providing raw data (if using boxplot) or outlier data (if using boxplot prepared), but not the box parameters. Those always need to be provided directly using the boxplot prepared={...} options.

You can, however, write a couple of wrapper styles that read the values from a table and set the required keys. That would allow you to write something like

\addplot+[
  boxplot prepared from table={
    table=\datatable,
    lower whisker=lw,
    upper whisker=uw,
    lower quartile=lq,
    upper quartile=uq,
    median=med
  }, boxplot prepared
  ]
  coordinates {};
\addplot+[
  boxplot prepared from table={
    table=\datatable,
    row=1,
    lower whisker=lw,
    upper whisker=uw,
    lower quartile=lq,
    upper quartile=uq,
    median=med
  }, boxplot prepared
  ]
  coordinates {};

to get


\documentclass[crop=false]{standalone}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.8}
\usepgfplotslibrary{statistics}
\makeatletter
\pgfplotsset{
    boxplot prepared from table/.code={
        \def\tikz@plot@handler{\pgfplotsplothandlerboxplotprepared}%
        \pgfplotsset{
            /pgfplots/boxplot prepared from table/.cd,
            #1,
        }
    },
    /pgfplots/boxplot prepared from table/.cd,
        table/.code={\pgfplotstablecopy{#1}\to\boxplot@datatable},
        row/.initial=0,
        make style readable from table/.style={
            #1/.code={
                \pgfplotstablegetelem{\pgfkeysvalueof{/pgfplots/boxplot prepared from table/row}}{##1}\of\boxplot@datatable
                \pgfplotsset{boxplot/#1/.expand once={\pgfplotsretval}}
            }
        },
        make style readable from table=lower whisker,
        make style readable from table=upper whisker,
        make style readable from table=lower quartile,
        make style readable from table=upper quartile,
        make style readable from table=median,
        make style readable from table=lower notch,
        make style readable from table=upper notch
}
\makeatother


\pgfplotstableread{
    lw lq med  uq uw
     5  7 8.5 9.5 10
     4  5 6.5 8.5 9.5
}\datatable


\begin{document}
\begin{tikzpicture}
\begin{axis}[boxplot/draw direction=y]
  \addplot+[
  boxplot prepared from table={
    table=\datatable,
    lower whisker=lw,
    upper whisker=uw,
    lower quartile=lq,
    upper quartile=uq,
    median=med
  }, boxplot prepared
  ]
  coordinates {};
  \addplot+[
  boxplot prepared from table={
    table=\datatable,
    row=1,
    lower whisker=lw,
    upper whisker=uw,
    lower quartile=lq,
    upper quartile=uq,
    median=med
  }, boxplot prepared
  ]
  coordinates {};
\end{axis}
\end{tikzpicture}
\end{document}
6
  • 2
    Ouch, I knew it should be possible but didn't think it would take this much poking around in the pgfplots innards. Works like a charm though :)
    – ThomasH
    Jun 3, 2013 at 14:54
  • 1
    Any chance of adjusting this for multiple box plots read from a single file? I've tried replacing \pgfplotstablegetelem{0}{#1} with \pgfplotstablegetelem{\coordindex}{#1} but that only draws two copies of the same boxplot, presumably because the data table gets copied for each box plot. I've edited to the question accordingly
    – ThomasH
    Jun 3, 2013 at 21:29
  • @ThomasH perhaps consider opening a new question with this new request. The original question was already answered (and you had accepted it). In my opinion, the new requirement, although related, should go in its own question (the ideal in this site is one question per post). Jun 3, 2013 at 21:37
  • @GonzaloMedina I was contemplating that but the answer to the updated question would be equally valid for the original, if not better, as it would be more general. The change in the MWE is literally one line (the second line of data in the table). However, if people feel strongly about it, I have no qualms opening a separate question.
    – ThomasH
    Jun 3, 2013 at 21:45
  • Also, sincere apologies for accepting early. I usually wait a day or so, but Jake's answer was working so well until I properly looked through my actual requirements. I removed the accepted mark for the moment so that people won't think the update has already been addressed.
    – ThomasH
    Jun 3, 2013 at 21:47

You must log in to answer this question.

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