PGFPlots:计算并将平均值添加到散点图

PGFPlots:计算并将平均值添加到散点图

在我的源 CSV 文件中,每个数据系列有一列,因此我使用\foreach迭代器遍历所有数据系列并将其添加到散点图中。我还想添加一个 TikZ 节点来标记并说明每列的平均值。

梅威瑟:

\documentclass{standalone}

\usepackage{pgfplots}
\usepackage{pgfplotstable}
\pgfplotsset{
  compat=1.18,
  height=5cm,
  width=5cm,
  ymin=0,
}

\begin{document}

  \begin{tikzpicture}
    % load table
    \pgfplotstableread{
      typeA typeB typeC
      9     14    5
      10    14    3
      11    14    7
      9     14    6
      9     14    4
      11    13    5
      11    15    8
    }\loadedtable

    % get number of rows
    \pgfplotstablegetrowsof{\loadedtable}
    \newcommand*{\loadedrows}{\pgfplotsretval}

    % using pre-calculated number of rows
    \newcommand{\average}[1]{%
      \pgfkeys{/pgf/fpu}%
      \pgfmathsetmacro\buffer{0.0}%
      \pgfplotstableforeachcolumnelement{#1}\of\loadedtable\as\cellValue{%
        \pgfmathsetmacro{\buffer}{\buffer + \cellValue}%
      }%
      \pgfmathsetmacro{\buffer}{\buffer / \loadedrows)}%
      \pgfmathprintnumber{\buffer}%
    }

    % calculating number of rows on the fly
    \newcommand{\averagetwo}[1]{%
      \pgfkeys{/pgf/fpu}%
      \pgfmathsetmacro\buffer{0.0}%
      \pgfmathsetmacro\rows{0}%
      \pgfplotstableforeachcolumnelement{#1}\of\loadedtable\as\cellValue{%
        \pgfmathsetmacro{\buffer}{\buffer + \cellValue}%
        \pgfmathsetmacro{\rows}{\pgfplotstablerow + 1}%
      }%
      \pgfmathsetmacro{\buffer}{\buffer / \rows)}%
      \pgfmathprintnumber{\buffer}%
    }

    \node at (2, -1) {Type A avg: \average{typeA}};

    \begin{axis}[
      xtick={1,2,3},
      xticklabels={A,B,C}
    ]
      \foreach \type [count=\ctr] in {typeA,typeB,typeC} {%
         \addplot [only marks, mark options={opacity=.3}]
          table[x expr={\ctr}, y={\type}] {\loadedtable};


          % (1)
          %\node[fill=orange] at (\ctr, 1) {x};

          % (2*)
          %\edef\tmp{\noexpand\node[fill=orange] at (\ctr, 1) {\ctr};}
          %\tmp

          % (3)
          %\edef\tmp{\noexpand\node[fill=orange] at (\ctr, 1) {\averagetwo{\type}};}
          %\tmp

          % (4)
          %\edef\tmp{\noexpand\node[fill=orange] at (\ctr, \average{\type}) {x};}
          %\tmp

          % (5)
          %\edef\tmp{\noexpand\node[fill=orange] at (\ctr, 1) {\noexpand\average{\type}};}
          %\tmp

          % (6*)
          \edef\tmp{\noexpand\node[fill=orange] at (\ctr, 1) {\noexpand\averagetwo{\type}};}
          \tmp

          % (7)
          %\edef\tmp{\noexpand\node[fill=orange] at (\ctr, \noexpand\averagetwo{\type}) {x};}
          %\tmp
      }
    \end{axis}
  \end{tikzpicture}
\end{document}

计算表列的平均值有两种实现方式,均基于https://tex.stackexchange.com/a/252360第一个函数用于\pgfplotstablegetrowsof查找一次行数,第二个函数用于在每次调用时计算行数。

创建图表本身没有问题。但在星号上添加平均值的各种尝试中,都没有成功。


(1)

./mwe.tex:91: Undefined control sequence.
<argument> \ctr 
                , 1
l.91     \end{axis}

我推测这与某种程度上延迟执行代码的内部原因有关axis,此时计数器不再可访问。


(2*)通过手动扩展计数器来解决这个问题,虽然可以工作,但还远远没有达到我的目标。


(3)+(4)导致无限循环。当我中断编译时,我得到

^C./mwe.tex:90: Interruption.
\pgfkeys@parse ...uturelet \pgfkeys@possiblerelax 
                                                  \pgfkeys@parse@main 
l.90       }

好的,但\average不知何故这似乎是个问题。


(5)

./mwe.tex:91: Package PGF Math Error: Could not parse input '' as a floating po
int number, sorry. The unreadable part was near ''. (in '1Y7.0e1]/ )').

See the PGF Math package documentation for explanation.
Type  H <return>  for immediate help.
 ...                                              
                                                  
l.91     \end{axis}

由于某种原因\loadedrows这里是空的。


在这种情况下,替代平均值计算有效(6*),但不会改变以前的错误。这是我最接近目标的一次。请注意,外面的 TikZ 节点axis工作正常。

示例结果 (6*)


(7)导致与(3)和(4)相同的无限循环。


我的问题:

  • 如何为每个数据系列添加一个节点,标记该系列的平均值并以文本形式包含平均值。最好这些节点应具有可从外部访问的名称axis
  • \average(6)为什么会失败?怎么会\loadedrows突然为空?
  • \average我在里面直接使用会出现无限循环的原因是什么axis
  • (不是主要问题的直接部分,但相关:如何避免循环{typeA,typeB,typeC}中的列表\foreach并直接从 CSV 中获取列名?

相关内容