在下面的 MWE 中,有两个表,每个表中有一列(公共)x 值和两列 y 值(A 和 B)。在对每个表的 B 列的最大值进行归一化之后,它们绘制在同一张图中(还添加了一个偏移量)。
如何用 B 列和 A 列之间的面积代替每个表的 B 列最大值的归一化?换句话说:我想将每组两条曲线归一化为 B 和 A 之间的面积。如何实现?
虽然从数值上来说不是很复杂,但我不知道如何在 pgfplots 中实现它(这将消除每次绘制此图时将数据放入和取出 Matlab 或 Octave 的需要)。
梅威瑟:
\documentclass{article}
\usepackage[tightpage,active]{preview}
\usepackage{pgfplotstable}
\newcommand{\offset}{1}
\newcommand{\findmax}[3]{
\pgfplotstablesort[sort key={#2},sort cmp={float >}]{\sorted}{#1}%
\pgfplotstablegetelem{0}{#2}\of{\sorted}%
\pgfmathsetmacro#3{\pgfplotsretval}
}
\pgfplotstableread{
X A B
0 1 5
1 1 7
2 2 7
3 2 5
4 2 3
}\tableone
\findmax{\tableone}{B}{\Bmaxone}
\pgfplotstableread{
X A B
0 10 24
1 13 45
2 24 66
3 26 33
4 26 27
}\tabletwo
\findmax{\tabletwo}{B}{\Bmaxtwo}
\begin{document}
\begin{preview}
\begin{tikzpicture}
\begin{axis}
\addplot [black]
table[x=X,y expr=\thisrow{A}/\Bmaxone] {\tableone};
\addplot [black]
table[x=X,y expr=\thisrow{B}/\Bmaxone] {\tableone};
\addplot [black]
table[x=X,y expr=\thisrow{A}/\Bmaxtwo+\offset] {\tabletwo};
\addplot [black]
table[x=X,y expr=\thisrow{B}/\Bmaxtwo+\offset] {\tabletwo};
\end{axis}
\end{tikzpicture}
\end{preview}
\end{document}
答案1
计算曲线下的面积需要一点循环,但它相当简单。
请注意,如果您有很多数字,或者值很大(总计超过 16000),则需要使用该fpu
库,如下例所示。
\documentclass{article}
\usepackage{pgfplotstable}
\newcommand{\calcarea}[3]{
\pgfplotstablegetrowsof{#1}
\pgfmathtruncatemacro\numrows{\pgfplotsretval-1}
\pgfkeys{/pgf/fpu=true}
\def\cumsum{0}
\pgfplotstableforeachcolumnelement{#2}\of{#1}\as\elem{
\pgfmathparse{\cumsum+\elem}
\def\cumsum{\pgfmathresult}
}
\pgfplotstablegetelem{0}{#2}\of{#1}%
\pgfmathparse{2*\cumsum-\pgfplotsretval}
\def\cumsum{\pgfmathresult}
\pgfplotstablegetelem{\numrows}{#2}\of{#1}
\pgfmathparse{(\cumsum-\pgfplotsretval)/2}
\pgfmathfloattofixed{\pgfmathresult}
\edef#3{\pgfmathresult}
\pgfkeys{/pgf/fpu=false}
}
\pgfplotstableread{
X A B
0 1 5
1 1 7
2 2 7
3 2 5
4 2 3
}\tableone
\pgfplotstableread{
X A B
0 10 2400
1 13 4500
2 24 6600
3 26 3300
4 26 2700
}\tabletwo
\begin{document}
\calcarea{\tableone}{A}{\areaA}
\calcarea{\tableone}{B}{\areaB}
\calcarea{\tabletwo}{A}{\areaAtwo}
\calcarea{\tabletwo}{B}{\areaBtwo}
\begin{tikzpicture}
\begin{axis}
\addplot [black]
table[x expr=\coordindex,y expr=\thisrow{A}/abs(\areaA-\areaB)] {\tableone};
\addplot [black]
table[x expr=\coordindex,y expr=\thisrow{B}/abs(\areaA-\areaB)] {\tableone};
\addplot [red]
table[x=X,y expr=\thisrow{A}/abs(\areaAtwo-\areaBtwo)+0.5] {\tabletwo};
\addplot [red]
table[x=X,y expr=\thisrow{B}/abs(\areaAtwo-\areaBtwo)+0.5] {\tabletwo};
\end{axis}
\end{tikzpicture}
\end{document}