我想在 pgfplot 中添加一条直线来表示数据的平均值。对于直方图,这应该是一条垂直线;对于简单图,应该是一条水平线。现在,我已经在提供的最小工作示例中做到了这一点。
\documentclass{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.9}
\begin{filecontents}{data.csv}
1.84919
0.97280
4.78586
3.95797
4.50753
2.52274
5.13984
0.29474
5.39946
4.40204
\end{filecontents}
\newcommand*{\manmean}{3.3832}
\begin{document}
\begin{tikzpicture}
\begin{axis}
\addplot[hist={bins=6,}, fill=teal, draw=teal!50!black] table[y index=0] {data.csv};
\addplot[teal, ultra thick, dashed] coordinates {(3.3832, 0) (3.3832, 3)};
\end{axis}
\end{tikzpicture}
%
\begin{tikzpicture}
\begin{axis}
\addplot[teal, mark=*] table [x expr=\coordindex+1, y index=0] {data.csv};
\addplot[teal, ultra thick, dashed] coordinates {(1, \manmean) (10, \manmean)};
\end{axis}
\end{tikzpicture}
\end{document}
然而,仍然存在两个问题:
- 需要手动计算平均值
- 需要手动输入线路的起点和终点
实际上,这条线应该沿着轴的整个延伸延伸并触及边界。
pgfplots 手册中提到/pgfplots/xmin
,,/pgfplots/xmax
以及/pgfplots/ymin
/pgfplots/ymax
4.14.1 限值范围配置/pgfplots/boxplot/average
.还有5.11 统计。但是,我找不到访问这些值的方法。
理论上,我可以使用以下公式计算平均值awk。然而,这并不奏效,因为pdflatex不知何故无法使用带有printf
引号的 shell 命令进行编译。
\documentclass{standalone}
\usepackage{pgfplots}
\usepackage{filecontents}
\pgfplotsset{compat=1.9}
\begin{filecontents*}{data.csv}
1.84919
0.97280
4.78586
3.95797
4.50753
2.52274
5.13984
0.29474
5.39946
4.40204
\end{filecontents*}
\begin{document}
\begin{tikzpicture}
\begin{axis}
\addplot[teal, mark=*] table [x expr=\coordindex+1, y index=0] {data.csv};
\addplot[teal, ultra thick, dashed, mark=*] shell {awk '{ sum += $1 } END { printf "%i %f\n%i %f\n", 1, sum/NR, NR, sum/NR }' data.csv};
\end{axis}
\end{tikzpicture}
\end{document}
-shell-escape
请注意,编译包含 shell 脚本的文档时需要参数,例如pdflatex -shell-escape mwe-mean-awk.tex
。
它给出的错误:
Runaway argument?
{awk '{ sum += $1 } END { printf "\end {axis} \end {tikzpicture} \end \ETC.
! Paragraph ended before \pgfplots@addplotimpl@shell@opt was complete.
<to be read again>
\par
l.25
?
即使这种方法可行,但对于一张漂亮的照片来说,这条线还是太短了。
答案1
这是一个选项:
\documentclass[varwidth=100cm,border=5pt]{standalone}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.9}
\usepackage{filecontents}
\begin{filecontents*}{data.csv}
level
1.84919
0.97280
4.78586
3.95797
4.50753
2.52274
5.13984
0.29474
5.39946
4.40204
\end{filecontents*}
\usepackage{filecontents}
\begin{filecontents*}{dataA.csv}
level
2
4
6
8
10
9
7
5
3
1
\end{filecontents*}
\newcommand\DrawVMean[1][]{
\draw[#1]
(axis cs:\Mean,\pgfkeysvalueof{/pgfplots/ymin}) --
(axis cs:\Mean,\pgfkeysvalueof{/pgfplots/ymax});
}
\newcommand\DrawHMean[1][]{
\draw[#1]
(axis cs:\pgfkeysvalueof{/pgfplots/xmin},\Mean) --
(axis cs:\pgfkeysvalueof{/pgfplots/xmax},\Mean);
}
\newcommand\GetMean[2]{
\pgfplotstableread{#1}\tableA
\pgfplotstableset{
create on use/new/.style={
create col/expr={\pgfmathaccuma + \thisrow{#2}}},
}
\pgfplotstablegetrowsof{\tableA}
\pgfmathsetmacro{\NumRows}{\pgfplotsretval}
\pgfplotstablegetelem{\numexpr\NumRows-1\relax}{new}\of{#1}
\pgfmathsetmacro{\Sum}{\pgfplotsretval}
\pgfmathsetmacro{\Mean}{\Sum/\NumRows}
}
\begin{document}
\begin{tikzpicture}
\GetMean{data.csv}{level}
\begin{axis}
\addplot[hist={bins=6,}, fill=teal, draw=teal!50!black] table[y index=0] {data.csv};
\DrawVMean[teal, ultra thick, dashed]
\end{axis}
\end{tikzpicture}\qquad
%
\begin{tikzpicture}
\GetMean{data.csv}{level}
\begin{axis}
\addplot[teal, mark=*] table [x expr=\coordindex+1, y index=0] {data.csv};
\DrawHMean[teal, ultra thick, dashed]
\end{axis}
\end{tikzpicture}\par\bigskip
\begin{tikzpicture}
\GetMean{dataA.csv}{level}
\begin{axis}
\addplot[hist={bins=6,}, fill=cyan!20, draw=cyan!50!black] table[y index=0] {dataA.csv};
\DrawVMean[orange, ultra thick, dashed]
\end{axis}
\end{tikzpicture}\qquad
%
\begin{tikzpicture}
\GetMean{dataA.csv}{level}
\begin{axis}
\addplot[cyan!50, mark=*] table [x expr=\coordindex+1, y index=0] {dataA.csv};
\DrawHMean[orange, ultra thick, dashed]
\end{axis}
\end{tikzpicture}
\end{document}
结果:
解释
- 用于获取文件中
\GetMean{<data-file>}{<col-name>}
具有名称的列的平均值。<col-name>
<data-file>
- 在
axis
环境中使用\DrawVMean[<options>]
/\DrawHMean[<options>]
在媒体位置自动绘制垂直/水平线。