使用 pgfplots 的累积二项分布

使用 pgfplots 的累积二项分布

这是声明 pgfplots 使用的函数

数学家协会

\documentclass{article}

\usepackage{pgfplots} 

\usetikzlibrary{arrows.meta}
\pgfplotsset{compat=1.15}

\begin{document}

\begin{tikzpicture}
[
  declare function = {binom(\x,\y) = \x! / \y! / (\x - \y)!;},
  declare function = {binompdf(\x,\y,\z) = binom(\x, \z) * \y^\z * (1 - \y)^(\x - \z);}
]
\begin{axis}
[
  grid = none,
  tick style = {black},
  tick label style = {
    /pgf/number format/use comma,
    /pgf/number format/fixed,
    /pgf/number format/fixed zerofill},
  scaled ticks = false,
  % x axis
  xmin = 0, xmax = 0.01,
  axis x line = middle, x axis line style = -{Stealth},
  xlabel = $p$, xlabel style = {below},
  xtick = {0, 0.001, ..., 0.01}, xticklabels = {},
  extra x ticks = {0.001},
  xticklabel style = {/pgf/number format/precision = 3},
  % y axis
  ymin = 0, ymax = 1.1,
  axis y line = middle, y axis line style = -{Stealth},
  ylabel = $P(X \ge 10)$, ylabel style = {left},
  ytick = {0, 0.1, ..., 1.1}, yticklabels = {},
  extra y ticks = {0.1},
]
\addplot[domain = 0 : 0.01, samples = 100] {0.8};
\addplot[domain = 0 : 0.01, samples = 100] {1 - binompdf(2100, x, 0) - binompdf(2100, x, 1) - binompdf(2100, x, 2) - binompdf(2100, x, 3) - binompdf(2100, x, 4) - binompdf(2100, x, 5) - binompdf(2100, x, 6) - binompdf(2100, x, 7) - binompdf(2100, x, 8) - binompdf(2100, x, 9)};
\end{axis}
\end{tikzpicture}

\end{document}

产生以下结果:

MWE 的输出

存在三个问题:

  1. 计算不太准确(见下面的 Maple 输出)。这可能是由于计算 2100! 时中间结果很大。
  2. LaTeX 需要很长时间来编译文档。
  3. 写第二条\addplot命令很不方便。有没有办法声明一个函数来进行累计?

枫叶输出

答案1

这解决了所有三个问题。仅对于 2) 在一定程度上:

real    0m5.005s
user    0m4.964s
sys     0m0.036s

嗯,实际上我没有对原始代码进行计时。这是它,但在比用于上述计时的计算机慢约 20% 的计算机上。

real    3m56.351s
user    3m55.698s
sys     0m0.387s

因此,尽管情节仍然需要几秒钟,但速度提高了约 40 倍。

我们用xintexpr

编辑:原始答案对 进行了一些不必要的修改\pgfmathfloatvalueof。但它可以直接使用。我在其他地方犯了一些错误,导致我认为它需要更改以使其可扩展。但通常意义上的可扩展性就足够了。因此,下面\FVof就是将输入从 传递到 所需的全部pgf内容\xintfloatexpr

\documentclass{article}

\usepackage{pgfplots} 

\usetikzlibrary{arrows.meta}
\pgfplotsset{compat=1.15}

% I was very happy to find \pgfmathfloatvalueof in TikZ/pgf manual
\def\FVof(#1){\pgfmathfloatvalueof{#1}}

\usepackage{xintexpr}

\begin{document}

\begin{tikzpicture}
[
% original declarations
%  declare function = {binom(\x,\y) = \x! / \y! / (\x - \y)!;},
%  declare function = {binompdf(\x,\y,\z) = binom(\x, \z) * \y^\z * (1 - \y)^(\x - \z);}
% declaration using xintexpr.sty
  declare function = {cumulbinompdf(\x,\y,\z) = \xintthefloatexpr
   add(binomial(\FVof(\x),i) * \FVof(\y)^i * (1 -\FVof(\y))^(\FVof(\x)- i),
       i = 0..\FVof(\z)
       )
   \relax;}
]
\begin{axis}
[
  grid = none,
  tick style = {black},
  tick label style = {
    /pgf/number format/use comma,
    /pgf/number format/fixed,
    /pgf/number format/fixed zerofill},
  scaled ticks = false,
  % x axis
  xmin = 0, xmax = 0.01,
  axis x line = middle, x axis line style = -{Stealth},
  xlabel = $p$, xlabel style = {below},
  xtick = {0, 0.001, ..., 0.01}, xticklabels = {},
  extra x ticks = {0.001},
  xticklabel style = {/pgf/number format/precision = 3},
  % y axis
  ymin = 0, ymax = 1.1,
  axis y line = middle, y axis line style = -{Stealth},
  ylabel = $P(X \ge 10)$, ylabel style = {left},
  ytick = {0, 0.1, ..., 1.1}, yticklabels = {},
  extra y ticks = {0.1},
]
\addplot[domain = 0 : 0.01, samples = 100] {0.8};
\addplot[domain = 0 : 0.01, samples = 100] {1 - cumulbinompdf(2100, x, 9)};
\end{axis}
\end{tikzpicture}

\end{document}

在此处输入图片描述

binomial警告:该函数有一个缺陷,\xintfloatexpr即它确实接受浮点输入,但是截断将它们转换为整数。它应该圆形的将它们转换为整数。同样,i = 0..Z如果我没记错的话,构造将截断为整数Z。它应该四舍五入。

在本例中,我认为变量是足够小的整数,因此在 pgf 处理中不会出现舍入误差,因此当它们达到\xintfloatexpr截断时确实会产生误差2100,而不是2099每次都产生误差。我猜图形中不会显示出太大的差异(没有考虑过)。

它也适用于

  declare function = {cumulbinompdf(\x,\y,\z) = \xintthefloatexpr
   add(binomial(\FVof{\x},i) * \FVof{\y}^i * (1 -\FVof{\y})^(\FVof{\x}- i),
       i = 0..\FVof{\z}
       )
   \relax;}

然后\let\FVof\pgfmathfloatvalueof它只是一个别名。但我发现将上述内容定义\FVof为宏并使用括号作为分隔符更加美观,这样宏定义中就不需要使用括号了。

相关内容