PDLの基礎を学ぼう
R言語で統計解析を行っている人が、PerlでのPDLを使った統計解析作業を行えるように、PDLの入門を書いてみたいと思います。Perlの統計解析ライブラリであるPDLが使えるようになれば、Excelで行うような複数列のデータの統計処理が行えるようになります。
まずもっとも簡単な1次元のデータ構造を作成してみましょう。次のコードを見てください。pdl関数を利用すると、1次元のデータ構造を作成することができます。
use strict; use warnings; use PDL; # データの作成 my $nums = pdl [2, 4, 7]; # データの出力 print $nums;
このサンプルを実行すると、画面には次のように出力されます。
[2 4 7]
PDL変数の作成
まずpdl関数を使用するとPDL変数を作成することができます。まずPDLの最低限の機能を利用するためのPDLを読み込みます。
use PDL;
PDLを読み込むとpdl関数を使用できるようになります。PDL変数を作成するにはpdl関数を使用します。
my $nums = pdl [2, 4, 7];
データの取得と変更
pdl関数で作成されたデータは、PDL変数と呼ばれます。1次元のPDL変数の要素を取得してみましょう。データを取得するにはatメソッドを使用します。
my $first = $nums->at(0); my $second = $nums->at(1);
上記の例では、PDL変数に含まれる要素の値を取得しましたけれど、PDL変数として取得することもできます。
一部のデータをPDL変数として取得するには、いくつかの方法がありますがナイススライス記法で記述するのが簡単です。ナイススライス記法を記述するためのPDL::NiceSliceモジュールを読みましょう。これはスクリプトの先頭で行っておきます。
use PDL::NiceSlice;
要素をPDL変数として取得するには$変数名(要素番号)という記法を使用します。
# 要素をPDL変数として取得 my $pdl_first = $nums(0); my $pdl_second = $nums(1);
これらはPDL変数ですから、要素の値自体を取得したければatメソッドで取り出すことができます。
my $first = $pdl_first->at(0); my $second = $pdl_second->at(0);
要素の値の変更を行う場合はも、ナイススライス記法を使用します。.=演算子を使用します。.=は文字列の結合ではなくて、代入のためにオーバーライドされています。
# 要素の値を変更 $nums(0) .= 5;
PDLではPDL変数の複数の部分を新しいPDL変数として切り出すこともできます。二番目と三番目の要素を切り出して見ましょう。次のように$変数名(n:m)という記法を利用すると、PDL変数の一部を切り出すことができます。
my $pdl_parts = $nums(1:2);
切り出したPDL変数のすべての要素に値を代入することもできます。
$nums(1:2) .= 8;
このように切り出した部分の集合に対して、同じ演算を行うことができるのがPDLの特徴になっています。
1次元のデータの長さを取得してみましょう。データの長さを取得するにはdimsメソッドを使用します。
my $length = $nums->dims;
サンプル
実行できるサンプルです。
use strict; use warnings; use PDL; use PDL::NiceSlice; # データの作成 my $nums = pdl [2, 4, 7]; # 要素の出力 print $nums->at(0) . "\n"; print $nums->at(1) . "\n"; # PDL変数の取り出し my $pdl_first = $nums(0); my $pdl_second = $nums(1); # 代入 $nums(0) .= 5; # 複数要素のPDL変数の取得 my $pdl_parts = $nums(1:2); # PDL変数として取り出した複数の要素への代入 $nums(1:2) .= 8; print $nums . "\n";
定数の四則演算
PDL変数のすべての値に同じ値を加算するには+演算子を使用します。
use PDL; my $pdl = pdl [1, 1, 2, 2, 2, 3]; my $pdl_add = $pdl + 3;
引き算、掛け算、割り算、商、べき乗も同じように計算することができます。
# 引き算 my $pdl_sub = $pdl - 3; # 掛け算 my $pdl_product = $pdl * 3; # 割り算 my $pdl_div = $pdl / 3; # 商 my $pdl_quotient = $pdl % 3; # べき乗 my $pdl_pow = $pdl + 3;
掛け算と割り算にによるものは、ベクトルの定数倍に該当します。PDL変数どうしの演算ではなくて、PDL変数と普通の値との演算を行っていることを意識に止めておきましょう。
ユニークな値を取り出す
ユニークな値を取り出すにはuniqメソッドを使用します。
my $pdl_uniq = $pdl->uniq;
PDL変数どうしの四則演算
PDL変数どうしを加算するには、PDL変数どうしに対して+演算子を使用します。各要素が加算されます。
# PDL変数どうしの加算 my $pdl1 = pdl [1, 2, 3]; my $pdl2 = pdl [4, 5, 6]; my $pdl_add = $pdl1 + $pdl2;
引き算、掛け算、割り算、商、べき乗も同じように計算することができます。各要素が計算されます。
# 引き算 my $pdl_sub = $pdl1 - $pdl2; # 掛け算 my $pdl_product = $pdl1 * $pdl2; # 割り算 my $pdl_div = $pdl1 / $pdl2; # 商 my $pdl_quotient = $pdl1 % $pdl2; # べき乗 my $pdl_pow = $pdl1 + $pdl2;
加減算は、ベクトルの加減算に該当します。
内積
内積を計算する特別な方法はありません。内積を計算するにはPDL変数どうしの掛け算を行ってから、その和を求めます。
# 内積 my $inner_product = ($pdl1 * $pdl2)->sum;
内積の結果は、PDL変数ではなくって、ただの値になります。
サンプル
実行できるサンプルです。
use strict; use warnings; use PDL; # 足し算 my $pdl = pdl [1, 1, 2, 2, 2, 3]; my $pdl_add = $pdl + 3; # 引き算 my $pdl_sub = $pdl - 3; # 掛け算 my $pdl_product = $pdl * 3; # 割り算 my $pdl_div = $pdl / 3; # 商 my $pdl_quotient = $pdl % 3; # ユニークな値を取得 my $pdl_uniq = $pdl->uniq; # 計算結果 print "$pdl_add\n"; print "$pdl_sub\n"; print "$pdl_product\n"; print "$pdl_div\n"; print "$pdl_quotient\n"; print "$pdl_uniq\n";
use strict; use warnings; use PDL; # PDL変数どうしの加算 my $pdl1 = pdl [1, 2, 3]; my $pdl2 = pdl [4, 5, 6]; my $pdl_add = $pdl1 + $pdl2; # 引き算 my $pdl_sub = $pdl1 - $pdl2; # 掛け算 my $pdl_product = $pdl1 * $pdl2; # 割り算 my $pdl_div = $pdl1 / $pdl2; # 商 my $pdl_quotient = $pdl1 % $pdl2; # べき乗 my $pdl_pow = $pdl1 + $pdl2; # 内積 my $inner_product = ($pdl1 * $pdl2)->sum; # 計算結果 print "$pdl_add\n"; print "$pdl_sub\n"; print "$pdl_product\n"; print "$pdl_div\n"; print "$pdl_quotient\n"; print "$inner_product\n";