各ポイントでの確率分布の高さを計算できる Perl のパッケージはありますか。たとえば、これは R で次のように行うことができます。
> dnorm(0, mean=4,sd=10)
> 0.03682701
つまり、ポイント x=0 の確率は、平均値が 4 で sd=10 の正規分布に入る確率は 0.0368 です。私はStatistics::Distributionを見ましたが、それを行うためのまさにその機能を提供していません。
各ポイントでの確率分布の高さを計算できる Perl のパッケージはありますか。たとえば、これは R で次のように行うことができます。
> dnorm(0, mean=4,sd=10)
> 0.03682701
つまり、ポイント x=0 の確率は、平均値が 4 で sd=10 の正規分布に入る確率は 0.0368 です。私はStatistics::Distributionを見ましたが、それを行うためのまさにその機能を提供していません。
dnorm(0, mean=4, sd=10) は、そのような点が発生する可能性を与えません。ウィキペディアの確率密度関数を引用するには
確率論では、確率密度関数 (pdf) (確率分布関数1とも呼ばれます)または確率変数の密度は、サンプル空間の各点での確率の密度を表す関数です。確率変数が特定のセット内に収まる確率は、セット全体の密度の積分によって与えられます。
そして、あなたが言及する確率は
R> pnorm(0, 4, 10)
[1] 0.3446
または、N(4, 10) 分布から 0 以下の値が得られる確率は 34.46% です。
Perl の質問について: R でそれを行う方法を知っているが、Perl からそれが必要な場合は、R の libRmath (パッケージ r-mathlib によって Debian で提供される) に基づいて Perl 拡張機能を作成して、それらの関数を取得する必要があるかもしれません。パール?これには R インタープリターは必要ありません。
それ以外の場合は、GNU GSL または Cephes ライブラリを試して、これらの特別な機能にアクセスできます。
これらの行に沿って何かしないのはなぜですか (私は R で書いていますが、Perl で Statistics::Distribution を使用して実行できます):
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] コピー アンド ペースト エラーを修正しました。
密度関数が本当に必要な場合は、直接使用しないでください。
$pi = 3.141593;
$x = 2.02;
$mean = 2;
$sd = .24;
print 1/($sd * sqrt(2*$pi)) * exp(-($x-$mean)**2 / (2 * $sd**2));
R の dnorm とほぼ同じ 1.65649768474891 が得られます。
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);
}
他の人が指摘したように、おそらく累積分布関数が必要です。これは、標準数学ライブラリに存在し、 Math::Libmによって Perl でアクセスできるようになっているエラー関数(平均によってシフトされ、正規分布の標準偏差によってスケーリングされる)を介して取得できます。
CPAN のMath::SymbolicX::Statistics::Distributionsモジュールを使用して、R で行っているのと同じことを Perl で行う方法を次に示します。
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() 関数は、関数のジェネレーターです。$norm は、変更可能なMath::Symbolic (::Operator) オブジェクトになります。たとえば、上記の例では、2 つのパラメーター変数を定数に置き換えます。
ただし、ダークが指摘したように、おそらく正規分布の累積関数が必要であることに注意してください。または、より一般的には、特定の範囲の積分。
残念ながら、Math::Symbolic はシンボリックに積分を行うことができません。したがって、Math::Integral::Rombergなどの数値積分に頼る必要があります。(あるいは、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
これにより、Dirk's answer から ~0.344578258389676 が得られるはずです。