获取 pgfplotstable 中某一行的值,该行位于当前行上方 x 行

获取 pgfplotstable 中某一行的值,该行位于当前行上方 x 行

我想进行计算来绘制图表。但我找不到获取已加载数据文件中某一行某一列的值的方法。

如何获取当前行上方 14 行单元格的值?对于前一行,有\prevrowno{1},其中“1”表示列号。

我在 MWE 中写了几行伪代码。但我不知道如何获取可用的代码\GetRowVal。我见过这个回答,但未能制定出可行的解决方案。

我真的希望我在这里的描述清楚。请询问,我很乐意提供更多解释。

我的 MWE:

\documentclass[paper=landscape, DIV=30]{scrarticle}

\usepackage{pgfplots}
\usepackage{pgfplotstable}

\begin{filecontents}{Verdoppelungszeit.csv}
Tag BRD
2020-03-10  654
2020-03-11  1089
2020-03-12  1892
2020-03-13  2576
2020-03-14  3421
2020-03-15  4195
2020-03-16  5433
2020-03-17  7156
2020-03-18  8198
2020-03-19  10999
2020-03-20  13957
2020-03-21  16662
2020-03-22  18610
2020-03-23  22672
2020-03-24  27436
2020-03-25  31554
2020-03-26  36508
2020-03-27  42288
2020-03-28  48582
2020-03-29  52547
2020-03-30  57298
2020-03-31  61913
2020-04-01  67366
2020-04-02  73522
2020-04-03  79696
2020-04-04  85778
2020-04-05  91714
\end{filecontents}

\pgfplotsset{compat=1.17}
\usepgfplotslibrary{dateplot}


\begin{document}

%\pgfplotstableread{Verdoppelungszeit.csv}\loadedtable

%%% Does not work!
%\newcommand{\GetRowVal}[1]{%
%  Value of Column 1, #1 Rows abvoe Current Row
%}

\newcommand{\Subtraction}[1]{%
  \thisrowno{1} - \GetRowVal{#1}
}

\pgfplotstableset{% WORKS
  create on use/brdoppel/.style=
  {create col/expr={ln(2)/(ln((\thisrowno{1}-\prevrowno{1})/\prevrowno{1}+1))}}
}

%\pgfplotstableset{% HOW CAN I DO THIS?
%  create on use/brdoppelALT/.style=
%  {create col/expr={ln(2)/(ln((\thisrowno{1}-\prevrowno{1})/
%      \Subtraction{14}+1))}}
%}

\begin{tikzpicture}
  \begin{semilogyaxis}[
    width=20cm,
    unbounded coords=discard,
    xlabel=Datum, grid=major,
    date coordinates in=x,
    xtick = data,
    x tick label style={rotate=45,anchor=north east},
   ]

\addplot [blue, ultra thick]
          table [%
          x=Tag, y=BRD, xlabel style={font=\sffamily}]{Verdoppelungszeit.csv};

\addplot+ [blue, mark=*,mark options={fill=white}, thin,
          restrict y to domain=0.1:inf]
          table [x=Tag, y=brdoppel]{Verdoppelungszeit.csv};

%% Does not work!
%\addplot+ [yellow, mark=*,mark options={fill=white}, thin,
%          restrict y to domain=0.1:inf]
%          table [x=Tag, y=brdoppelALT]{Verdoppelungszeit.csv};

  \end{semilogyaxis}
\end{tikzpicture}

\end{document}

一个非常好的额外功能是进行测试,如果存在当前行上方 14 行(例如),则如果不存在,则整个术语的计算就没有结果。


编辑

评论中的问题:你想计算什么。简短回答:参见这里

我正在尝试计算感染人数翻倍的时间。公式是

ln(2) / ln(q),其中 q = 1 + p/100

数据来自韋科页。

现在,几周过去了,计算结果非常具有误导性,因为恢复健康的人数不见了。3 月初被感染的人要么健康​​,要么……然而,他们不会感染任何人,所以在我看来,继续将他们考虑在内是错误的。

因此,我想“抹去”所有曾经被感染但将来不会感染任何人的人的数量,因为他们感染的时间太久了。

一种简单的方法(记住:这不是科学,而是在摆弄数字)似乎是取新感染人数(这是\thisrowno{1} - \prevrowno{1}),然后减去在某个时间之前(比如说 14 天)感染的所有人数。我们得到一个粗略的数字,有多少人可能具有传染性今天。这是计算加倍所需时间的基数。

要减去 14 天前被感染的人数,我只需查看数据,但我无法将其输入到代码中!

答案1

pgfplotstable 只能访问前后行中的值。您可以自然地将列移动 14 次以访问其他值,但我会将这些值存储在 expl3 序列中,然后您可以访问任何值并进行任何您想要创建新列的计算:

\documentclass[paper=landscape, DIV=30]{scrarticle}

\usepackage{pgfplots}
\usepackage{pgfplotstable}

\begin{filecontents}{Verdoppelungszeit.csv}
Tag BRD
2020-03-10  654
2020-03-11  1089
2020-03-12  1892
2020-03-13  2576
2020-03-14  3421
2020-03-15  4195
2020-03-16  5433
2020-03-17  7156
2020-03-18  8198
2020-03-19  10999
2020-03-20  13957
2020-03-21  16662
2020-03-22  18610
2020-03-23  22672
2020-03-24  27436
2020-03-25  31554
2020-03-26  36508
2020-03-27  42288
2020-03-28  48582
2020-03-29  52547
2020-03-30  57298
2020-03-31  61913
2020-04-01  67366
2020-04-02  73522
2020-04-03  79696
2020-04-04  85778
2020-04-05  91714
\end{filecontents}

\pgfplotsset{compat=1.17}
\usepgfplotslibrary{dateplot}

\pgfplotstableread{Verdoppelungszeit.csv}\datatable
\ExplSyntaxOn
\seq_new:N\l_keks_data_seq
\pgfplotstableforeachcolumnelement{BRD}\of\datatable\as\yvalue
 {
   \seq_put_right:NV \l_keks_data_seq {\yvalue}
 }

\pgfplotstablecreatecol[create~col/assign/.code={%
  \int_compare:nNnTF {\pgfplotstablerow-14}<1 
   { 
     \tl_set:Nx \entry{0}
   } 
   {
     \tl_set:Nx \entry{\seq_item:Nn \l_keks_data_seq {\pgfplotstablerow-14}}
   } 
   \pgfkeyslet{/pgfplots/table/create~col/next~content}\entry
  }]{shift14}\datatable

\pgfplotstablecreatecol[create~col/assign/.code={%
   \tl_set:Nx \entry{\fp_eval:n{\seq_item:Nn \l_keks_data_seq {{\pgfplotstablerow+1}/2}}}
   \pgfkeyslet{/pgfplots/table/create~col/next~content}\entry
  }]{half}\datatable


 \ExplSyntaxOff

\begin{document}
\pgfplotstabletypeset[string type]\datatable
\end{document}  

在此处输入图片描述

答案2

绘制一些“延迟”数据点非常容易。诀窍是定义一个element返回表元素的 pgf 函数。此函数可用于以下构造:

y expr={element(\coordindex,1)-element(\coordindex-14,1)}

\getelem该函数是宏的一个几乎简单的实现,其微妙之处在于它涉及由和整数开启的pgfplotstable相互作用。fpufpu

以下绘制了原始数据和延迟版本。它还计算了倍增时间,即在给定日期病例数翻倍所需的时间。它们有两个版本,一个使用全部病例数,另一个仅查看过去 14 天内的病例。

\documentclass[tikz,border=3mm]{standalone}

\usepackage{pgfplots}
\usepackage{pgfplotstable}

\begin{filecontents}{Verdoppelungszeit.csv}
Tag BRD
2020-03-10  654
2020-03-11  1089
2020-03-12  1892
2020-03-13  2576
2020-03-14  3421
2020-03-15  4195
2020-03-16  5433
2020-03-17  7156
2020-03-18  8198
2020-03-19  10999
2020-03-20  13957
2020-03-21  16662
2020-03-22  18610
2020-03-23  22672
2020-03-24  27436
2020-03-25  31554
2020-03-26  36508
2020-03-27  42288
2020-03-28  48582
2020-03-29  52547
2020-03-30  57298
2020-03-31  61913
2020-04-01  67366
2020-04-02  73522
2020-04-03  79696
2020-04-04  85778
2020-04-05  91714
\end{filecontents}
\pgfplotsset{compat=1.17}
\usepgfplotslibrary{dateplot}


\begin{document}
\pgfplotstableread{Verdoppelungszeit.csv}\mydata
\pgfplotstablegetrowsof{\mydata}%
\pgfmathtruncatemacro{\numrows}{\pgfplotsretval}%


\pgfmathdeclarefunction{element}{2}{\begingroup
\pgfkeys{/pgf/fpu,/pgf/fpu/output format=fixed}%
\pgfmathtruncatemacro{\myindex}{max(0,#1)}%
\pgfmathtruncatemacro{\mycol}{#2}%
\pgfplotstablegetelem{\myindex}{[index]\mycol}\of\mydata%#1=row, #2=column
\edef\pgfmathresult{\pgfplotsretval}%
\pgfmathsmuggle\pgfmathresult
\endgroup}

\begin{tikzpicture}
  \begin{semilogyaxis}[
    width=20cm,
    unbounded coords=discard,
    xlabel=Datum, grid=major,
    date coordinates in=x,
    xtick = data,
    x tick label style={rotate=45,anchor=north east},
    legend style={at={(0.01,0.99)},anchor=north west,font=\sffamily,
    legend cell align=left}
   ]


\addplot [blue, ultra thick]
          table [%
          x=Tag, y=BRD, xlabel style={font=\sffamily}]{Verdoppelungszeit.csv};

\addlegendentry{F\"alle}          

\addplot [red, ultra thick]
          table [%
          x=Tag, y=BRD, xlabel style={font=\sffamily},
          y expr={element(\coordindex,1)-element(\coordindex-14,1)}]{Verdoppelungszeit.csv};

\addlegendentry{Neue F\"alle (weniger als 14 Tage alt)}       

\addplot [blue, mark=*,mark options={fill=white}, thin]
          table [x=Tag, 
          y expr={ln(2)/ln(1+(element(\coordindex,1)-element(\coordindex-1,1))%
            /element(\coordindex,1))}]{Verdoppelungszeit.csv};

\addlegendentry{Verdoppelungszeit}                  

\addplot [red, mark=*,mark options={fill=white}, thin]
          table [x=Tag, 
          y expr={ln(2)/ln(1+(element(\coordindex,1)-element(\coordindex-1,1))%
            /(element(\coordindex,1)-element(\coordindex-14,1)))}]{Verdoppelungszeit.csv};

\addlegendentry{Verdoppelungszeit von neuen F\"allen}                   
\end{semilogyaxis}
\end{tikzpicture}

%% ADDENDUM

\pgfmathdeclarefunction{melement}{2}{\begingroup
\pgfkeys{/pgf/fpu,/pgf/fpu/output format=fixed}%
\pgfmathtruncatemacro{\myindex}{#1}%
\pgfmathtruncatemacro{\mycol}{#2}%
\ifnum\myindex<0
\edef\pgfmathresult{0}%
\else
\pgfplotstablegetelem{\myindex}{[index]\mycol}\of\mydata%#1=row, #2=column
\edef\pgfmathresult{\pgfplotsretval}%
\fi
\pgfmathsmuggle\pgfmathresult
\endgroup}


\pgfplotstablenew[
% define how the 'new' column shall be filled:
create on use/data/.style={create col/expr={%
melement(\pgfplotstablerow,1)}},
create on use/shifted data/.style={create col/expr={%
melement(\pgfplotstablerow-14,1)}},
columns={data,shifted data}]
{\numrows}
\loadedtable

\pgfplotstabletypeset[columns={data,shifted data}]\loadedtable

\end{document}

在此处输入图片描述

还请注意,如附录所示,上述函数类型的函数element也可以用于排版表格。

相关内容