我如何计算在给定一个正态分布在Perl点的概率是多少?(How can I compute the

2019-08-03 17:23发布

是否有Perl的一个包,让你计算概率分布的高度在每个给定的点。 例如,这在R中可以做到这样:

> dnorm(0, mean=4,sd=10)
> 0.03682701

即点x = 0的概率落入正态分布,平均= 4和SD = 10,是0.0368。 我看着统计::分布 ,但它不会给这很函数来做到这一点。

Answer 1:

为什么不沿着这些线路的东西(我写在R,但它可以用Perl来完成与统计::分布):

dn <- function(x=0 # value
               ,mean=0 # mean 
               ,sd=1 # sd
               ,sc=10000 ## scale the precision
               ) {
  res <- (pnorm(x+1/sc, mean=mean, sd=sd)-pnorm(x, mean=mean, sd=sd))*sc
  res
}
> dn(0,4,10,10000)
0.03682709
> dn(2.02,2,.24)
1.656498

[编辑:1]我应该指出,这种近似可以得到在最尾部相当可怕的。 它可能会或可能不会不管这取决于您的应用程序。

[编辑:2] @foolishbrat拐过码成一个函数。 结果应该始终是积极的。 也许你忘记了Perl模块,在你提到的函数返回上概率为1-F和R返回F·

[编辑:3]固定复制和粘贴误差。



Answer 2:

dnorm(0,平均= 4,SD = 10) 给你THR这样的点发生的概率。 引述维基百科上的概率密度函数

在概率理论, -通常被称为概率分布函数的概率密度函数(pdf) 1 -或密度,随机变量的是描述在样品空间中的每个点的概率密度函数。 一个随机变量落在给定组内的概率是由它的密度超过设定的积分给出。

你提的概率

R> pnorm(0, 4, 10)
[1] 0.3446

或从N(4,10)分布得到等于一个值或小于0的34.46%的机会。

至于你的Perl的问题:如果你知道如何做到这一点的R,但需要它的Perl,也许你需要编写基于R的libRmath Perl扩展(通过包r-mathlib在Debian中提供)来获取这些功能Perl的? 这并不需要将R解释。

否则,你可以尝试在GNU GSL或Cephes库访问这些特殊功能。



Answer 3:

如果你真的想密度函数,为什么不直接使用它:

$pi = 3.141593;
$x = 2.02;
$mean = 2;
$sd = .24;
print 1/($sd * sqrt(2*$pi)) * exp(-($x-$mean)**2 / (2 * $sd**2));

它给1.65649768474891关于一样R. dnorm



Answer 4:

我不认为Jouni是完全正确的。 这似乎给PDF(提取循环的中间,如果你只是想要一个特定的XY点)的合理版本:

!/usr/bin/perl

use strict;
use Getopt::Std;
use POSIX qw(ceil floor);

# Usage
# Outputs normal density function given a mean and sd
# -s standard deviation
# -m mean
# -n normalization factor (multiply result by this amount), optional

my %para = ();
getopts('s:m:n:', \%para);
if (!exists ($para{'s'}) || !exists ($para{'m'})) {
   die ("mean and standard deviation required");
}

my $norm = 1.0;
if (exists ($para{'n'})) {
   $norm = $para{'n'};
}

my $sd = $para{'s'};
my $mean = $para{'m'};

my $start = floor($mean - ($sd * 5));
my $end = ceil($mean + ($sd * 5));

my $pi = 3.141593;

my $var = $sd**2;

for (my $x = $start; $x < $end; $x+=0.1) {
    my $e = exp( -1 * (($x-$mean)**2) / (2*$var));
    my $d = sqrt($var) * sqrt(2*$pi);
    my $y = 1.0/$d*$e * $norm;
    printf ("%5.5f %5.5f\n", $x, $y);
}


Answer 5:

正如其他人所指出的那样,你可能想的累积分布函数。 这可以通过获得误差函数 (由平均位移和缩放通过您的正常分布的标准偏差),它存在于标准的数学库,并通过取得访问在Perl 数学:: libm中 。



Answer 6:

使用Perl的统计::分布,你可以做到这一点:

#!/usr/bin/perl

use strict; use warnings;
use Statistics::Distributions qw(uprob);

my $x       = 0;
my $mean    = 4;
my $stdev   = 10;

print "Height of probablility distribution at point $x = "
    . (1-uprob(($x-$mean)/$stdev))."\n";

结果与“probablility分布的高度在点0 = 0.34458”



Answer 7:

这里是你怎么做你有R在Perl使用做同样的事情数学:: SymbolicX ::统计::分布模块从CPAN:

use strict; use warnings;

use Math::SymbolicX::Statistics::Distributions qw/normal_distribution/;

my $norm = normal_distribution(qw/mean sd/);
print $norm->value(mean => 4, sd => 10, x => 0), "\n";

# curry it with the parameter values
$norm->implement(mean => 4, sd => 10);
print $norm->value(x => 0),"\n"; # prints the same as above

从该模块的normal_distribution()函数是用于功能的发电机。 $规范将是一个数学符号:: (::运营商)的对象,你可以修改。 例如用工具 ,其中,在上面的例子中,代替两个参数变量与常量。

但是请注意,因为德克指出的那样,那你可能要正态分布的累积函数。 或者更一般地在一定范围内的积分。

不幸的是,数学::符号不能做集成象征。 因此,你不得不求助于与喜欢数值积分数学::积分::容安澜 。 (另外,搜索CPAN的误差函数的实现)。这可能是缓慢的,但它仍然是很容易做到。 此添加到上面的代码片段:

use Math::Integral::Romberg 'integral';

my ($int_sub) = $norm->to_sub(); # compile to a faster Perl sub
print $int_sub->(0),"\n";  # same number as above

print "p=" . integral($int_sub, -100., 0) . "\n";
# -100 is an arbitrary, small number

这应该给你〜0.344578258389676从德克的回答。



文章来源: How can I compute the probability at a point given a normal distribution in Perl?