北大地環研講習会 2002.09.17
北大苫小牧研究林講習会 2002.10.11
最近の更新 ::DATE::

プログラミング言語 Perl 「ちょー」入門篇

久保拓弥   kubo@ees.hokudai.ac.jp   要旨

今日の論点

  • データ解析を自動化するご利益
  • 当世ウケする Perl のナゾの一端を
  • まずはぢりぢりと取り組んでみる

今日の行程

  1. Perl 概論
  2. Perl 演習
  3. Perl consulting
camel

「ラクダは醜い生き物だが,特定の作業をこなすには最適の生き物」

(Perl camel なンだが, まぁ書影なんで OK かな,というような)

もっとちゃんとした解説を読みたいひとは, 解説本買うとか竹中さんの 生物系研究者のための Perl 基礎の基礎 などで勉強してください. (2002.10.22)

(Netscape 4.* のようなヘタれブラウザーでみるとかなりツラいです)

Page 00

(投影資料一覧)

Page 01

生態学研究とプログラミング

自動処理のご利益

手間が省ける,そして解析のハバが拡がる

手作業の「暗黒面」 (dark side)

るーく 「暗黒面の力の方が強いのでしょうか?」
よーだ 「違う …… 暗黒面は心の中にたやすく生まれやすく陥りやすい …… 暗黒面に一度陥ればそれに食い尽くされる」 (S.W. Ep.V)

(cf. E*cel 根絶は可能か? その他アンチゑくせる文書)

試行錯誤くりかえし,データ構造をよく考えて,自動化した例

foliage -> individual tree
個葉 → 個体
野外実験結果の解析
  Abies stand age 28
個体 → 個体群 (1)
「自己間引き」再現 *
  
PopWave
個体 → 個体群 (2)
遺伝子の流れの計算
  OFR 1987
個体群 → 群落・群集
毎木調査結果の解析

Page 02

べつに Perl でなくてもいいんだが

とりあえず,Perl

実用重視の言語であり,解説も多く,どこでも動く

``Perl'' (ぱーる) の意味は?

このふざけた世界の背後には……

Page 03

Perl の哲学

作者 Larry Wall のシュミ的世界

L. Wall
Larry Wall

Perl はひどく私的なモノだ

この哲学ゆえに, たとえば Perl は「なんとーりもの書き方」 を許容する言語になっている.


Page 04

使用例 (1) ファイル内容変換

基本中の基本ワザ

file filter

Perl は「テキストファイル」の取り扱いをもっとも得意としている. 今日もテキストファイルの読み書きだけを説明する. なお, E*cel などに拉致されているデータを解析したいときには, 「テキストファイルとして保存」 してそれを Perl に読みこませる.


Page 05

使用例 (2) 統計計算もシミュレイションも自作

これも自動化 & 脱 black box 統計学

logistc.pm
一般化ロジスティック回帰 logistic.pm

宮本さんの統計パッケージ Pstat 解説ペイジとか見よ


Page 06

使用例 (3) 作図・作表も自動化

図表作るのに電気鼠はいらない !

Perl コンビネイション作画ワザの例

PovRay と連動

PipeTrees OFR Fagus Japonica

Gnuplot と連動

PJP stem growth

Perl/Tk モジュールを使って

forest 0100
forest 1000

Perl による自動作表 (in HTML) の一例

樹種 個体数 MLL2 MLL3 AIC (その結果) 尤度比検定 (その結果)
ACM 427 129.5 131.6 4.27 明るさ依存 0.0388 明るさ依存
ACP 1266 507.7 520.0 24.51 明るさ依存 0.0000 明るさ依存
ACR 235 -6.1 -5.9 0.41 明るさ無関係 0.5232 明るさ無関係
ACS 185 166.1 176.2 20.28 明るさ依存 0.0000 明るさ依存
ACT 206 90.7 95.9 10.26 明るさ依存 0.0000 明るさ依存
BTG 105 11.3 16.8 11.01 明るさ依存 0.0000 明るさ依存
CLB 373 412.6 423.2 21.11 明るさ依存 0.0000 明るさ依存
COC 380 -22.9 -18.0 9.83 明るさ依存 0.0000 明るさ依存
COK 156 192.8 192.8 0.00 明るさ無関係 1.0000 明るさ無関係
CRC 1351 307.3 318.0 21.53 明るさ依存 0.0000 明るさ依存
CRJ 144 118.4 118.5 0.23 明るさ無関係 0.6334 明るさ無関係
CRL 1370 933.7 939.3 11.23 明るさ依存 0.0000 明るさ依存
CRT 245 99.4 105.2 11.73 明るさ依存 0.0000 明るさ依存
CSC 169 -45.4 -45.0 0.82 明るさ無関係 0.3638 明るさ無関係
FGC 305 19.6 19.6 0.01 明るさ無関係 0.9318 明るさ無関係
FGJ 1744 378.4 381.4 5.82 明るさ依存 0.0158 明るさ依存
FRL 188 153.4 154.3 1.80 明るさ依存 0.1791 明るさ無関係
MLM 238 153.3 161.6 16.58 明るさ依存 0.0000 明るさ依存
OSJ 185 41.9 42.2 0.56 明るさ無関係 0.4548 明るさ無関係
PRV 208 17.8 21.1 6.51 明るさ依存 0.0107 明るさ依存
QRM 126 -4.3 -0.6 7.39 明るさ依存 0.0065 明るさ依存
QRS 885 -345.5 -333.4 24.18 明るさ依存 0.0000 明るさ依存
STO 1460 1027.7 1053.4 51.42 明るさ依存 0.0000 明るさ依存
ZZZ 1219 392.7 437.3 89.11 明るさ依存 0.0000 明るさ依存

Page 07

基本 (1) データ構造

スカラー・配列・ハッシュ・参照

スカラー: 数字と文字列

$name = "kubo";             # $name を "kubo"
$full_name = $name." taku"; # $full_name は "kubo taku"
$weight = 71.8;             # 浮動小数点数
$bmi = $weight / 1.77**2;   # 演算して代入

Perl では文字列と数値の区別がない (「文脈」によって判断される)

配列: スカラーをならべたもの

# 配列を初期化
@trees = ("イタヤカエデ", "サワシバ", "シナノキ");
push @trees, "エゾマツ"; # 最後尾に追加
$tree = shift @trees;    # 先頭から削除して取り出し
print $trees[0];          # "サワシバ" と表示 (0 から始まる)

ハッシュ: スカラーの「辞書」

# ハッシュを初期化
%tree_name = (                  # キーと値をセット
	"QRS" => "コナラ",
	"FGJ" => "イヌブナ",
	"FGC" => "ブナ"
	"QRS number" => 318,
	"FGJ number" => 695,
	"FGC number" => "?"
);
$tree_name{"FGC number"} = 115; # 上書き
print $tree_name{"FGJ"};        # "イヌブナ" と表示
print $tree_name{"FGC number"}; # 115 と表示

「キー」→「値」というふうに 「辞書のようにひく」ことができる. 小型データベイスのようなもの.

参照: (今日は説明しない)

$reference = \%tree_name;

Page 08

基本 (2) 制御構造

条件分岐とぐるぐる回転

if: もしそうならこうしろ

# 条件分岐
if ($name eq "kubo") {    # $name が "kubo" なら
	$number_kubo++;   # $number_kubo を増加
}
else {                    # もしそうでないなら
	$number_others++; # $number_kubo を増加
}

# 倒置した書き方
print "Your BMI is too large" if $bmi >= 25.0;

foreach: 全部ひとつづつやれ

foreach $tree (@trees) { # @trees のすべての要素に
	print "$tree\n"; # 改行をつけて表示
}

while: ヨシというまで続けろ

# 1 から 10 までの和を計算
$i = 1;
$total = 0;
while ($i < 11) {
	$total += $i; # $total に $i を加える
	$i++;         # $i を増加
}
# foreach $i (1 .. 10) {...} としてもよい

# %tree_name からキーと値を全部取りだして表示
while (($key, $value) = each %tree_name) {
	print "$key : $value\n";
}

Page 09

基本 (3) 正規表現

つまりは検索と検索+置換

検索

$_ = "kubo takuya";          # 特殊変数に代入
print "found" if m/kubo/;    # もし kubo が含まれれば
print "found" if m/KUBO/i;   # 大文字小文字区別なし
print "found" if m/^kubo/;   # もし先頭が kubo であれば
print "found" if m/ya$/;     # もし末尾が ya ならば

検索+置換

$_ = "kubo takuya";          # 特殊変数に代入
s/k/K/g;                     # すべての k を K に
s/(^.+)( )(.+$)/$3 $1/;      # 入れ換え
print;                       # taKuya Kubo と表示

Page 10

Perl 高段者への道

Perl 使いへの道は高く険しい

ま,てきとーなところで切り上げてもらえば

初段 ファイル読みこんで操作して書き出せる, スカラーを使える
二段 配列・ハッシュを使える, 簡単な正規表現ならだいたいわかる
三段 自作関数を書ける, ラクダ本 使える
四段 参照を使える, perldoc 使える
五段 Perl 標準ライブラリ使える, strict に書ける
六段 簡単なモジュールを自作できる, Perl ふうオブジェクト指向がわかる
七段 Perl を C で拡張できる, 自作モジュールが CPAN に受理される
八段 Perl6 開発プロジェクトに参加・貢献する
九段 Larry Wall と友人づきあいする
十段 Larry Wall にとってかわる

Page 11

演習 (1) ファイル内容表示

ファイルを読みこんで表示する

# 標準入力から読みこまれた内容をそのまま表示するだけ
while (<>) { # 入力が続いてるかぎり繰りかえす
	print;
}

特殊変数

# まったく同じ内容,特殊変数 $_ を明示的に書いてるだけ
while ($_ = <>) {
	print $_;
}

ふつーのスカラー

# 特殊変数ではなくふつーのスカラーに入れてもよい
while ($line = <>) {
	print $line;
}
# この場合 $line は省略できない

ファイルに出力 (ファイルのコピー)

# 標準出力 (画面とか) ではなく別のファイルに出力する
open OUT, "> output.txt"; # 書き込み用に開く
while (<>) {
	print OUT;  # OUT に出力している
}
close OUT; # OUT を閉じて書き込めないようにする

Page 12

演習 (2) タテヨコ計算

ファイルを読みこんで成長量と集計計算

# 標準入力から読みこんだファイルの書式が
# 「樹種   直径2001年   直径2002年」と仮定する.
# 読みこんだ行に成長量 (= 直径2002 - 直径2001) を加えて出力し,
# 断面積合計もいっしょに計算していって最後に表示する.

# BA とかいう指標計算専用のサブルーチン (C 言語でいう関数)
sub calc_ba {
	my ($dbh) = @_;
	$ba = $dbh * $dbh * 3.1416 * 0.25;
	return $ba;
}

# まとめて初期化
($total_ba_2001, $total_ba_2002) = (0.0, 0.0);

# ファイル読みこんで計算するループ
while (<>) { # 入力が続いてるかぎり繰りかえす
	chomp;         # 行末の改行マークを削除
	next if m/^#/; # 行頭が # だったらその行はとばす
	($species, $dbh2001, $dbh2002) = split; # 行の分割・代入
	$growth = $dbh2002 - $dbh2001; # 成長量の計算
	# 表示
        print  "$species  $dbh2001\t$dbh2002\t";
	printf "%.2f\n", $growth;            # 書式つき出力
	# BA なる指標の計算していく
	$total_ba_2001 += calc_ba($dbh2001); # サブルーチン calc_ba
	$total_ba_2002 += calc_ba($dbh2002); # を呼び出している
}
# 書式つき出力 printf を用いる
print  "----------------------------\n";
printf "TBA  %.2e   %.2e\n", $total_ba_2001, $total_ba_2002;

(関連ファイル)


Page 13

演習 (3) 複数ファイルをまとめる

二つのファイルの情報をひとつに

# tree_name.txt に記されている樹種略号⇔和名の対応を記憶して
# それを樹木サイズデータといっしょにして output.txt に出力.

($tree_name_file, $dbh_file) = ("tree_name.txt", "dbh.txt");
open NAME, $tree_name_file
	or die "ERROR: Can't open $tree_name_file";
%tree_name;
while (<NAME>) { # NAME から読みこむ
	chomp;         # 行末の改行マークを削除
	next if m/^#/; # 行頭が # だったらその行はとばす
	($short_name, $name) = split; # 分割
	$tree_name{$short_name} = $name;
}
close NAME;

open DBH, $dbh_file
	or die "ERROR: Can't open $tree_name_file";
open OUT, "> output.txt";
while (<DBH>) { # DBH から読みこむ
	chomp;         # 行末の改行マークを削除
	next if m/^#/; # 行頭が # だったらその行はとばす
	($short_name, $dbh2001, $dbh2002) = split;
	printf OUT "%-8s\t", $tree_name{$short_name};
        print  OUT "$_\n";
}
close DBH;
close OUT;

(関連ファイル)


Go back to index