根据文件创建箱线图

根据文件创建箱线图

我的问题有点涉及此主题。我想从文件创建箱线图。文件(在我的情况下是 CSV)如下所示:

Upper,Lower,Min,Max,Median,Name
3,1,0,4,2,First
4,2,1,5,3,Second
...

有多个行,每行包含描述箱线图的数据点(中位数、晶须位置和箱线边界)和数据集名称的字段。我想根据这些数据创建多个箱线图。名称应添加为图例条目。

我曾尝试使用 CSV 阅读器:

\begin{tikzpicture}
  \begin{axis}[
    \csvreader[
      head to column names,
      separator=comma]
              {data.csv}{}% use head of csv as column names
              {
                \addplot+ [
                  boxplot prepared={
                    lower whisker=\Min,
                    lower quartile=\Lower,
                    median=\Median,
                    upper quartile=\Upper,
                    upper whisker=\Max,
                  },
                ] coordinates {};
              }
  \end{axis}
\end{tikzpicture}

但这会产生一个空图。我猜想宏(\Min等等)在tikzpicture/axis环境中无法正常工作?!(当我将图片外的值转储出来时,它可以正常工作)。

我也看了上面提到的话题。本例中的问题是,只绘制了表格的第一行,而我想绘制全部评论中提到了这个缺点,但没有提到该方法的扩展。

添加图的最佳方法是什么?

答案1

你可以将 Jake 的回答延伸到从表中读取箱线图准备好的值相当容易,使用\pgfplotsinvokeforeach

下面的代码基于 Jake 的回答,只做了一些修改:

  • 从表中获取行数的方法:

    \pgfplotstablegetrowsof{\datatable}
    \pgfmathtruncatemacro\TotalRows{\pgfplotsretval-1}
    

    减一,因为行/列号在索引中从 0 开始计数。

  • 一个循环而不是两个不同的\addplot

    \pgfplotsinvokeforeach{0,...,\TotalRows}{ \addplot .. }
    

    row=#1注意在箱线图选项中添加了,在\pgfplotsinvokeforeach循环中变量用表示#1

  • 添加area legend\addplot选项中,否则图例图像就是完整的(大)箱线图。

  • 从表中添加图例条目:

    \pgfplotstablegetelem{#1}{name}\of\datatable
    \addlegendentryexpanded{\pgfplotsretval}
    

代码输出

\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 name
     5  7 8.5 9.5 10 first
     4  5 6.5 8.5 9.5 second
}\datatable


\begin{document}
\begin{tikzpicture}
\begin{axis}[boxplot/draw direction=y]
\pgfplotstablegetrowsof{\datatable}
\pgfmathtruncatemacro\TotalRows{\pgfplotsretval-1}
\pgfplotsinvokeforeach{0,...,\TotalRows}
{
  \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,
  % to get a more useful legend
  area legend
  ]
  coordinates {};

  % add legend entry 
  \pgfplotstablegetelem{#1}{name}\of\datatable
  \addlegendentryexpanded{\pgfplotsretval}
}
\end{axis}
\end{tikzpicture}
\end{document}

相关内容