平滑 PGF 图

平滑 PGF 图

我正在尝试复制我在 Desmos 中创建的图表这里

使用 Overleaf 中的以下代码

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.7}

% https://tex.stackexchange.com/questions/198572/tikz-binomial-distribution

\begin{document}
\begin{tikzpicture}[
    declare function={binom(\x,\n,\p)=\n!/(\x!*(\n-\x)!)*\p^\x*(1-\p)^(\n-\x);},
    declare function={normd(\x,\n,\p)=binom(\x*\n,\n,\p);}
]

\begin{axis}
    \addplot[cyan, domain=0:1]{normd(x, 15, 0.7)};
\end{axis}

\end{tikzpicture}
\end{document}

但是,生成的图形并不平滑(而且相当粗糙): 锯齿状

我尝试增加样本数量,samples=500 和 samples at={0, 0.001, ..., 0.999, 1},但两者仍然无法复制 Desmos 产生的粒度。

是否有些函数很难通过 pgfplot 绘制?

答案1

如果我使用众所周知的关系Gamma(n+1)=n!来提供连续版本的阶乘,我会得到与 Ruixi 截然不同的结果。但是,结果似乎非常准确地匹配您的 Desmos 曲线,所以我认为这是正确的。Gamma来自这个答案,我用它来提供阶乘的连续泛化这里,遇到同样的问题时。

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}

% https://tex.stackexchange.com/questions/198572/tikz-binomial-distribution

\begin{document}
\begin{tikzpicture}[% gamma definition from https://tex.stackexchange.com/a/120449/121799
    declare function={gamma(\z)=(2.506628274631*sqrt(1/\z) + 0.20888568*(1/\z)^(1.5) +
    0.00870357*(1/\z)^(2.5) - (174.2106599*(1/\z)^(3.5))/25920 -
    (715.6423511*(1/\z)^(4.5))/1244160)*exp((-ln(1/\z)-1)*\z);
    smoothbinom(\x,\n,\p)=gamma(\n+1)/(gamma(\x+1)*gamma((\n-\x)+1))*pow(\p,\x)*(1-\p)^(\n-\x);
    smoothnormd(\x,\n,\p)=smoothbinom(\x*\n,\n,\p);
    }]

\begin{axis}
    \addplot[blue, domain=0:1,samples=100,smooth]{smoothnormd(x, 15, 0.7)};
\end{axis}
\end{tikzpicture}
\end{document}

在此处输入图片描述

交叉检查:我首先检查该Gamma功能是否已正确实现,然后用它绘制轮廓。

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}

% https://tex.stackexchange.com/questions/198572/tikz-binomial-distribution

\begin{document}
\begin{tikzpicture}[
    declare function={binom(\x,\n,\p)=\n!/(\x!*(\n-\x)!)*\p^\x*(1-\p)^(\n-\x);
    normd(\x,\n,\p)=binom(\x*\n,\n,\p);
    gamma(\z)=(2.506628274631*sqrt(1/\z) + 0.20888568*(1/\z)^(1.5) +
    0.00870357*(1/\z)^(2.5) - (174.2106599*(1/\z)^(3.5))/25920 -
    (715.6423511*(1/\z)^(4.5))/1244160)*exp((-ln(1/\z)-1)*\z);
    smoothbinom(\x,\n,\p)=gamma(\n+1)/(gamma(\x+1)*gamma((\n-\x)+1))*pow(\p,\x)*(1-\p)^(\n-\x);
    smoothnormd(\x,\n,\p)=smoothbinom(\x*\n,\n,\p);
    }]

\begin{axis}
    \addplot[cyan, domain=1:10,samples=10,only marks,mark=*]{x!};
    \addplot[blue, domain=1:10]{gamma(x+1)};
\end{axis}
\end{tikzpicture}


\begin{tikzpicture}[
    declare function={binom(\x,\n,\p)=\n!/(\x!*(\n-\x)!)*\p^\x*(1-\p)^(\n-\x);
    normd(\x,\n,\p)=binom(\x*\n,\n,\p);
    gamma(\z)=(2.506628274631*sqrt(1/\z) + 0.20888568*(1/\z)^(1.5) +
    0.00870357*(1/\z)^(2.5) - (174.2106599*(1/\z)^(3.5))/25920 -
    (715.6423511*(1/\z)^(4.5))/1244160)*exp((-ln(1/\z)-1)*\z);
    smoothbinom(\x,\n,\p)=gamma(\n+1)/(gamma(\x+1)*gamma((\n-\x)+1))*pow(\p,\x)*(1-\p)^(\n-\x);
    smoothnormd(\x,\n,\p)=smoothbinom(\x*\n,\n,\p);
    }]

\begin{axis}
    \addplot[cyan, domain=0:1]{normd(x, 15, 0.7)};
    \addplot[blue, domain=0:1]{smoothnormd(x, 15, 0.7)};
\end{axis}
\end{tikzpicture}
\end{document}

在此处输入图片描述

如您所见,绘图的平滑版本与带有阶乘的版本非常不同,但阶乘本身并未针对非整数进行定义。

答案2

添加:请注意,以下讨论基于我的概率论背景。在您的示例中,二项式概率仅在\x*\n为整数时才定义;也就是说,这些概率仅在\x等于以下 16 个数字之一时才定义

0, 1/15, 2/15, ... , 14/15, 15/15

因此,为了顺利地扩展图表,您有很多选择。这些扩展包括但不限于

  1. 通过分析延续伽马函数。但是,你应该意识到

    TeX 不是 Mathematica、MATLAB 或 Maple

    因此伽马函数无法即时使用。因此,@marmot 提供了一个很好的答案其中,伽马函数使用其渐近展开式进行硬编码。由于它使用渐近展开式,因此可能会出现意外的计算错误(但前提是您选择要绘制的极端域)。

  2. 使用smooth结合适当的样本点。 这smooth关键基本上使用样条函数在两点之间进行插值。通常使用两次连续可微分样条(三次样条),这足以欺骗人眼。这就是我在新答案中提出的建议。

  3. 使用高斯或正态密度近似。局部中心极限定理哪些州

    离散的二项式概率可以近似为连续的高斯/正态密度曲线\n*\p\n*(1-\p),近似值越好。(参见概率:理论与实例(第 4 版)由 Rick Durrett 编写,第 3.1 和 3.5 节)。

    这是我在以前的回答中提出的建议。

请注意,进行阶乘计算时必须小心! 如果你将实数传递给 binom,那么请准备好获得大于一的“概率”(参见我的这个问题)。在您的原始图表中,某些“概率”似乎大于二!

新答案

我刚刚意识到 OP 想要一个“正态化二项式概率质量图”而不是“正态密度近似图”。在这种情况下,你可以告诉 Ti\x*\nZ通过指定 来仅绘制为整数的点samples=\n+1记住要使用整数进行阶乘计算,然后再在坐标中进行规范化。

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.7}

% https://tex.stackexchange.com/questions/198572/tikz-binomial-distribution

\begin{document}
\begin{tikzpicture}[
    declare function={binom(\x,\n,\p)=\n!/(\x!*(\n-\x)!)*\p^\x*(1-\p)^(\n-\x);},
%    declare function={normd(\x,\n,\p)=binom(\x*\n,\n,\p);}% <- This is bad practice
]

\begin{axis}
    \addplot[cyan, samples at={0,1,...,15}, smooth](x/15,{binom(x, 15, 0.7)});
\end{axis}

\end{tikzpicture}
\end{document}

二项式

注意曲线的顶部在 左右 0.2。事实上,binom(11,15,0.7) = 0.218623131...


旧答案

这里我们使用“高斯/正态近似”。近似高斯/正态密度采用以下形式

1/sqrt(2 * pi * n * p * (1-p)) * exp( - n * (x - p)^2 / (2 * p * (1-p)) )

当然,如果n*pn*(1-p)更大,这种近似效果会更好。如果你要说明一个正态近似,那么这将是你的选择:

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.7}

% https://tex.stackexchange.com/questions/198572/tikz-binomial-distribution

\begin{document}
\begin{tikzpicture}[
    declare function={binom(\x,\n,\p)=\n!/(\x!*(\n-\x)!)*\p^\x*(1-\p)^(\n-\x);},
%    declare function={normd(\x,\n,\p)=binom(\x*\n,\n,\p);}% <- This is bad practice
    declare function={normaldensity(\x,\n,\p)=exp(-\n*(\x-\p)^2/(2*\p*(1-\p)))/sqrt(2*pi*\n*\p*(1-\p));}
]

\begin{axis}
    \addplot[cyan, samples at={0,1,...,15}, smooth](x/15,{binom(x, 15, 0.7)});
    \addplot[orange, domain=0:1, smooth]{normaldensity(x, 15, 0.7)};
\end{axis}

\end{tikzpicture}
\end{document}

普通的

这里,青色曲线是使用我的新答案绘制的,橙色曲线是使用正态近似绘制的。

相关内容