Pages

2011年10月30日日曜日

統計計算言語 R を試す

統計処理を扱う言語としては、商用のS、S-Plusが有名だが、オープンソースのRも負けていない。先日も丸善の数学コーナに顔を出したが、本棚の二段分はR関連の本が並んでいます。非常に多機能だ。まだ、チュートリアルを試してみただけだが、その可能性に驚いています。

R ホームページ
http://www.R-project.org/

テキストからのデータの取込み、データ構造として、ベクトル、マトリックス、リスト、複数のデータ形式を扱うデータフレームなどのデータ構造を扱うことができる。各種のグラフの出力も可能。手続きはインタラクティブに操作できるほか、もちろん、バッチ処理可能。Windows, Linux , MacOSXのパッケージが存在しています。

普通の人がデータ処理を扱うソフトとしては、ExcelやAccessが有名だが、Excelは、ドキュメント作成ソフトに成り下がっており、Accessは、アプリケーション開発環境に自分の行く末を決めたようだ。大量の企業データを黙々と自動的に処理し、有意義な結果を導き出すツールとして、Rは非常に好都合なのだ。

さて、インストール

OSXへのインストールは簡単。以下のサイトからダウンロードして、インストール・パッケージを実行。もちろん、他のOSもある。
http://cran.md.tsukuba.ac.jp/
すでに、Lionでの検証も済んでいるようで、すばやいなあ。

実行は、一文字 r と打てばOK
baker$ r

R version 2.13.2 (2011-09-30)
Copyright (C) 2011 The R Foundation for Statistical Computing
ISBN 3-900051-07-0
Platform: x86_64-apple-darwin9.8.0/x86_64 (64-bit)
Rは、自由なソフトウェアであり、「完全に無保証」です。 
一定の条件に従えば、自由にこれを再配布することができます。 
配布条件の詳細に関しては、'license()'あるいは'licence()'と入力してください。 

Rは多くの貢献者による共同プロジェクトです。 
詳しくは'contributors()'と入力してください。 
また、RやRのパッケージを出版物で引用する際の形式については 
'citation()'と入力してください。 

'demo()'と入力すればデモをみることができます。 
'help()'とすればオンラインヘルプが出ます。 
'help.start()'でHTMLブラウザによるヘルプがみられます。 
'q()'と入力すればRを終了します。 

データファイルの取込から演算まで

総務省・統計局のダウンロードから、「平成17年の福岡県人口統計」を入手。
http://www.stat.go.jp/data/guide/download/index.htm

本当は時系列データのほうが、面白そうなのだけど、この手のデータはワークシート毎に年度でまとめられている。とりあえず、平成17年の市町村別人口統計を使ってみる。

Appleご用達のNumberで整形。あまり、使っていないので使い方が判らん。最終的に、一行目をヘッダー(項目名)として、二行目以降をデータ部とする典型的なデータファイルにした。

なお、一行目の項目名は、以下のようにした。(日本語でも問題ないのだが、コンソールで操作するので、日本語変換は面倒だったため)

  • No -- 市町村番号(らしい)
  • Name -- 市町村名
  • m.u15 , f.o15 -- 男性15歳未満、女性15歳未満
  • m15.65 , f15.65 -- 15歳以上65歳以内 それぞれ男性、女性
  • m.o65, f.o65 -- 65歳以上。それぞれ、男性、女性

# 変数 fukuoka に、csvファイル "fukuoka-h17-x.csv"を読み込む read.csv()
> fukuoka <- read.csv("fukuoka-h17-x.csv")

fukuokaは、マトリックス型で登録されています。マトリックス型は、行列です。

> fukuoka
      NO     Name m.u15 m15.64 m.o65 f.u15 f15.64 f.o65
1  40101   門司区  6618  31509 11515  6288  34673 18044
2  40103   若松区  6081  26608  8181  5876  28214 12357
3  40105   戸畑区  4044  21171  5714  3896  20130  8743
4  40106 小倉北区 10798  58329 15939 10461  63276 24305
5  40107 小倉南区 16805  68123 17238 15836  73155 23348
6  40108 八幡東区  4154  22722  8345  3959  23557 13077
(省略)

このあたり、ちょっと疑問。チュートリアルでは、ベクトルもマトリックスも、その要素は全て同じ型です。数字と文字を混ぜることができません。なので、それを可能にするためにデータフレームがあるのですが、上記のように変数fukuokaには、一見 文字と数字が混在しているようにみえます。

実は、この取込は一度失敗しています。取込ファイルの各要素が”double quotation”で囲まれていたため、全て文字として扱われてしまい、演算ができなくなりました。もしかすると、上記の状態はマトリックス型なのかもしれません。

要素の名称を調べてみます。

> dimnames(fukuoka)
[[1]]
 [1] "1"  "2"  "3"  "4"  "5"  "6"  "7"  "8"  "9"  "10" "11" "12" "13" "14" "15"
[16] "16" "17" "18" "19" "20" "21" "22" "23" "24" "25" "26" "27" "28" "29" "30"
[31] "31" "32" "33" "34" "35" "36" "37" "38" "39" "40" "41" "42" "43" "44" "45"
[46] "46" "47" "48" "49" "50" "51" "52" "53" "54" "55" "56" "57" "58" "59" "60"
[61] "61" "62" "63" "64" "65" "66" "67" "68" "69" "70" "71" "72" "73" "74" "75"
[76] "76" "77" "78" "79" "80" "81" "82" "83" "84" "85" "86" "87" "88" "89" "90"
[91] "91" "92" "93" "94" "95" "96" "97"

[[2]]
[1] "NO"     "Name"   "m.u15"  "m15.64" "m.o65"  "f.u15"  "f15.64" "f.o65" 

[[1]]は、縦の要素をしめしています。特に指定していないため、登録順に番号が夫番されているようです。例えば、fukuoka[18,]と指定すると、18番目の行のデータすべてが表示されます。
[[2]]は、列要素の名前。csvファイルの一行目が指定されています。
名前要素は、例えば fukuoka$Name とすると、Name列の値一覧を表示しますし、Name列のみの行列(1列、x行の行列)として取り扱うことができます。
ただ、いちいち変数名を指定するのも面倒なので、attach()してやると、直接列名を使うことができます。つまり、fukuoka$f.u15 + fukuoka$m.u15は、 f.u15 + m.u15 と書けます。

以下は、attach()して、15歳以上65歳以下の比率を計算し、変数 rate.workersに格納しています。

> attach(fukuoka)
> workers <- m15.64 + f15.64
> total <- m.u15 + f.u15 + m.o65 + f.o65 + workers
> rate.workers<-workers/total

そうそう、Rの変数名は、.が使えますが、-+/*はつかえません。これらは、演算として処理されます。csvで取り込んだ時には、ご丁寧に、-は、.に置換されていました。(ヘッダー行のみ)

グラフをプロットする

簡単にできます。OSXでは、X11アプリケーションが起動し、表示します。

> hist(rate.workers , main="Histgram Rate of workers")



バッチ処理

処理を記述したファイルを実行することができる。他の言語などと組み合わせて利用すると、とても面白いことができそうだ。

以下のスクリプトは、パラメータを受け取って、上記の計算を実行した後、グラフはpdfに出力するようになっている。注意しなければならないのは、引数の扱い。引数は、ベクトルargsにセットするが、その添え字は、プログラム本体を1番目して順に格納されることだ。なんか、--argsオプションが意味ないような気がするが、このオプションのお陰で、それ以降の値は、何らかの意味を持たない(例えばオプションではない)値としてプログラムには無視されるのだろう。また、引数は文字列型なので、数字で扱いたい場合は、変換する必要がある。

# file name test.R
# パラメータを受け取る
args <- commandArgs()
# なぜ五番目なのかは、あとのコマンドをみてほしい
file <- args[5]
# pdfファイルを用意する。この時点でグラフの出力先は変更される。
pdf(file)

fukuoka <- read.csv("fukuoka-h17-x.csv")
attach(fukuoka)
workers <-m15.64 + f15.64
total <- m.u15 + f.u15 + m.o65 + f.o65 + workers
rate.workers<-workers/total
hist(rate.workers , main="Histgram Rate of workers")

# たぶん、出力デバイスの終了 pdfファイルのクローズか。
dev.off()

以下のように実行します。vanillaオプションはバッチモードを指定し、quietオプションは標準出力の制御、argsオプション以降にパラメータを書きます。Rは、基本インタラクティブなプログラムらしく、標準入力にスクリプトを食わせます。

> R --vanilla --quiet --args test1.pdf < test.R 

Rは、歴史もあり、機能も豊富で、多くのノウハウも公開されています。これからの勉強や仕事への応用がとても楽しいことになりそうです。

2011年10月22日土曜日

MacPortsを思い出す

このところ、localで作業せずリモート・ログイン & vim での開発と言う横着ぶり。
久しぶりにMacBookで、チョコチョコしようとしたら、いろいろと足りないものがあるようだ。改めて環境を整備することにして、まずはパッケージの更新とかやることにした。
(このあたりから、既に脇道にそれている。いつものことだが。まあ、今日は休みだし)

さて、mac portsを各種パッケージの利用のために使っている。各コマンドも忘れているので、主なコマンドを整理。
    sudo port selfupdate
    postコマンド自身とパッケージ情報を最新にする
    port search 検索文字
    パッケージ情報の検索
    sudo port install パッケージ
    指定したパッケージのインストール
    sudo port uninstall パッケージ
    パッケージのアンインストール
    sudo port valiants パッケージ
    パッケージ・インストール時に利用出来るオプションを表示
    sudo port install パッケージ +オプション +オプション ....
    オプション付でインストール
    sudo port deactivate パッケージ
    インストール済みのパッケージを利用不可にする
    sudo port activate パッケージ
    インストール済みの利用不可パッケージを利用可能にする
    port outdated
    古いパッケージを表示
    sudo port upgrade installed
    古いパッケージ全てをアップグレード
    sudo port upgrade パッケージ
    パッケージを指定してアップグレード

MacPortsはrpm,yumと異なり、ソースをダウンロードし、それをローカルでコンパイルする方式のパッケージ管理システムだ。そのため、XCodeも必要。
MacPortsは以前にインストールしているので、さっそく、アップグレード。
$ sudo port selfupdate
$ sudo port upgrade installed

注) selfupdateは、結局2回やりました。一回目はパッケージツリーの更新、二回目がport本体? 2.0.3 に更新された。

アップグレードの途中、perlのアップグレードでエラーが出て停止した。
--->  Activating perl5 @5.12.3_1+perl5_12
Error: Target org.macports.activate returned: Image error: /opt/local/bin/a2p is being used by the active perl5.8 port.  Please deactivate this port first, or use 'port -f activate perl5' to force the activation.
Error: Failed to install perl5
Log for perl5 is at: /opt/local/var/macports/logs/_opt_local_var_macports_sources_rsync.macports.org_release_ports_lang_perl5/perl5/main.log
Error: The following dependencies were not installed: perl5
Error: Problem while installing autoconf
To report a bug, see 

「このPort(perl5.8)を使用不可にするか、perl5を(強制的に)使用可にしろ」と言っております。現在の状況を調査。
$ port installed | grep perl
  perl5 @5.8.9_0
  perl5 @5.12.3_1+perl5_12
  perl5.8 @5.8.9_3 (active)
  perl5.12 @5.12.3_2 (active)
4つのバージョンが入っていて、2つが活性化しているのか? perl5.8.9_3を非活性化しました。

$ sudo port deactivate perl5.8 @5.8.9_3
$ sudo port upgrade outdated
これで、無事アップグレード終了。Perlの状態は

$ port installed | grep perl
  perl5 @5.8.9_0
  perl5 @5.12.3_1+perl5_12 (active)
  perl5.8 @5.8.9_3
  perl5.12 @5.12.3_2 (active)

まあ、いっか。perlは私の主力ではないので、この状態が問題ないのか不明。

MacPortsとは

http://macwiki.sourceforge.jp/wiki/index.php/MacPorts
MacPorts は MacOSX 上で利用可能なパッケージシステムの一つで、 主に UNIX 向けに開発されたオープンソース・ソフトウェアを手軽にインストールすることができます。 OpenDarwin プロジェクトの一部として 2002 年より始められ、 Landon Fuller, Kevin Van Vechten, Jordan Hubbard といった Apple inc. の従業員も多数参加しています。
以前は DarwinPorts と呼ばれていましたが、OpenDarwin プロジェクトの休止に伴い、MacPorts と改称(2006 年 8 月~)されました。 そのため、一部の配布物にはまだ DarwinPorts という表記が残っていますが、これらは全く同じものを指します。
2005 年 4 月 28 日にバージョン 1.0 がリリースされ、その当時でおよそ 2500 本のソフトウェア (ports) が導入可能でした。 最新版は 2010 年 11 月にリリースされたバージョン 1.9.2 で、7400 以上の ports が利用可能となっています。
MacPorts を使って新しくソフトウェアをインストールするには、ターミナル上で「sudo port install パッケージ名」などと入力します。 これによりアーカイブのダウンロード、展開、パッチの適用、コンフィグ、ビルドといった各段階を経て、 指定したソフトウェアのインストールが行われます。 このとき、他のパッケージに対する依存関係があれば、自動的にそれらの必要となるパッケージもインストールされます。

2011年10月10日月曜日

Ruby1.8.7とRuby1.9.2のWebApplicationをApacheで動かす

私のサクラVPSでは、いくつかのRailsアプリケーションが動いているが、それはRuby1.8.7ベースだ。
WebサーバにはApache(+ passenger module)を使い、VirtualHostで複数のWebアプリケーションを切り分けている。
さて、以前 開発用ユーザで Ruby1.9.2を試すためにrvmを導入した。
http://tech-baker.blogspot.com/2011/09/rvm-ruby-192-rails3.html
Apacheの実行環境では、デフォルトのruby1.8.7が動作してしまう。かといって、rvmをapache環境に導入したら、ruby1.8.7ベースのアプリケーションが動かない。ruby1.8.7もruby1.9.2もapache環境で動かしたい。以下のPassengerサイトを参考にチャレンジした。
http://blog.phusion.nl/2010/09/21/phusion-passenger-running-multiple-ruby-versions/

目指した環境は以下の図の通り。Apacheは、リバースプロキシとして利用され、ruby1.9.2のアプリケーションは、Passengerスタンドアローンで動かす。

図:Reverse Proxyを利用した複数Versionのruby Web app
Apache + passenger ----- app1.sample.com (ruby 1.8.7 + rails2.8.x)
Apache + passenger ----- app2.sample.com (ruby 1.8.7 + rails2.8.x)
Apache + mod_proxy ----- passenger ----- app3.sample.com ( ruby 1.9.2 + rails3 by rvm)


rails3アプリケーションは、開発ユーザdevmanのディレクトリ /home/devman/public_html/app3 に作成した。
rvm環境が出来ていることを前提で、作業は以下の手順
  1. passenger(スタンドアローン)のインストール
  2. apacheのプロキシー設定
  3. 起動スクリプト作成
  4. (必要であれば)iptablesをいじる

passengerのインストールはgemから行う。開発ユーザ環境も示しておいた。
devman$ rvm info
ruby-1.9.2-p290:

  system:
    uname:       "Linux www.miyabiit.com 2.6.18-274.3.1.el5 #1 SMP Tue Sep 6 20:13:52 EDT 2011 x86_64 x86_64 x86_64 GNU/Linux"
    bash:        "/bin/bash => GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu)"
    zsh:         " => not installed"

  rvm:
    version:      "rvm 1.8.3 by Wayne E. Seguin (wayneeseguin@gmail.com) [https://rvm.beginrescueend.com/]"

  ruby:
    interpreter:  "ruby"
    version:      "1.9.2p290"
    date:         "2011-07-09"
    platform:     "x86_64-linux"
    patchlevel:   "2011-07-09 revision 32553"
    full_version: "ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-linux]"

  homes:
    gem:          "/home/devman/.rvm/gems/ruby-1.9.2-p290"
    ruby:         "/home/devman/.rvm/rubies/ruby-1.9.2-p290"

  binaries:
    ruby:         "/home/devman/.rvm/rubies/ruby-1.9.2-p290/bin/ruby"
    irb:          "/home/devman/.rvm/rubies/ruby-1.9.2-p290/bin/irb"
    gem:          "/home/devman/.rvm/rubies/ruby-1.9.2-p290/bin/gem"
    rake:         "/home/devman/.rvm/gems/ruby-1.9.2-p290/bin/rake"

  environment:
    PATH:         "/home/devman/.rvm/gems/ruby-1.9.2-p290/bin:/home/devman/.rvm/gems/ruby-1.9.2-p290@global/bin:/home/devman/.rvm/rubies/ruby-1.9.2-p290/bin:/home/devman/.rvm/bin:/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/usr/lib/jvm/java/bin:/usr/local/ant/bin:/home/devman/bin"
    GEM_HOME:     "/home/devman/.rvm/gems/ruby-1.9.2-p290"
    GEM_PATH:     "/home/devman/.rvm/gems/ruby-1.9.2-p290:/home/devman/.rvm/gems/ruby-1.9.2-p290@global"
    MY_RUBY_HOME: "/home/devman/.rvm/rubies/ruby-1.9.2-p290"
    IRBRC:        "/home/devman/.rvm/rubies/ruby-1.9.2-p290/.irbrc"
    RUBYOPT:      ""
    gemset:       ""

devman$ gem install passenger --pre  # rvm 環境下なので userディレクトリにインストール

あれ、nginxもインストールされるのか。nginx(エンジンエックス、高速軽量で人気のWebサーバ)がスタンドアローンのwebサーバの役割を果たし、結局passenger本体はあくまでモジュールなのね。

ApacheにVirtualhostの設定を、reverse proxy仕様で追加する。
<VirtualHost *:80>
  ServerName app3.sample.com
  DocumentRoot /home/devman/public_html/words/public
  PassengerEnabled off
  ProxyPass / http://127.0.0.1:3000/
  ProxyPassReverse / http://127.0.0.1:3000/

</p>

起動スクリプトは、私は /etc/rc.d/app3をつくり、/etc/rc.localに追加した。これで良かったのかな。停止とかはKillしよう。chmod +x /etc/rc.d/app3を忘れないこと。

起動スクリプト:/etc/rc.d/app3
#!/bin/sh
su - devman -c 'cd public_html/app3;passenger start -a 127.0.0.1 -e development -p 3000 -d'
開発環境で実行している。
これで、Apacheを再起動し、rails3のアプリケーションを起動すればよい。
devman$ sudo /etc/init.d/httpd restart
devman$ cd public_html/app3
devman$ passenger start -a 127.0.0.1 -e development -p 3000 -d

リバースプロキシーは、高速化、キャッシュ・サーバ、負荷分散など応用が広いが、こういった使い方も出来るのですね。

2011年10月9日日曜日

Rubyの御気楽構造体クラス OpenStruct

OpenStructは、御気楽な構造体クラスで、予め定義しておかなくても、自動で属性を作成してくれます。

ずいぶん前に一度知ったのだが、クラスの名前をどうしても思い出せず検索できずに、利用したくても出来ない、とても歯がゆい思いをしていた。とっても便利なクラスである。

CodeRider:openstruct baker$ irb
>> require 'ostruct'
=> true
>> man = OpenStruct.new
=> #
>> man.name = 'masahiro'
=> "masahiro"
>> man.age = 200
=> 200
>> man.childs = %w(hanako taro)
=> ["hanako", "taro"]
>> p man
#

OpenStructをアプリケーションの初期設定に利用すると便利だ。
railsの場合、RAILS_ROOT/config/initializers/app_config.rbに以下のようなコードを書いておくと起動時に初期設定してくれる。

require 'ostruct'
AppConfig = OpenStruct.new

AppConfig.default_email = "no-reply@hoge.com"
AppConfig.api_url = "hoge.com"

ネタはここから
http://rubyquicktips.com/post/1718141794/use-openstruct-for-application-configuration-variables

2011年10月1日土曜日

PHP高速化のため APCを導入してみた

ブログエンジンとして非常に有名なWordPressを導入してみた。
さすがにインストールそのものは、とても簡単だったのだが、その時にサーバのメモリ不足問題が発生し、その対策として PHP-APC を導入したので、そのメモ。

php-apc

Alternative PHP Cashe
http://php.net/manual/ja/book.apc.php
phpの実行コードを高速化するためのPHPモジュールで、中間コードの最適化やキャッシュを提供する。

WordPressをインストールするまでの手順

# root になって、作業を進めました 
$ yum list installed | grep php
php.x86_64                               5.3.8-1.el5.remi              installed
php-cli.x86_64                           5.3.8-1.el5.remi              installed
php-common.x86_64                        5.3.8-1.el5.remi              installed
php-gd.x86_64                            5.3.8-1.el5.remi              installed
php-mbstring.x86_64                      5.3.8-1.el5.remi              installed
php-mysql.x86_64                         5.3.8-1.el5.remi              installed
php-pdo.x86_64                           5.3.8-1.el5.remi              installed
php-pgsql.x86_64                         5.3.8-1.el5.remi              installed

$ mysql -u root -p
Enter password: 
mysql> create database wordpress;
mysql> grant all on wordpress.* to wordpress@localhost identified  by 'xxxxxxx';

$ mkdir work
$ cd work/
$ wget http://ja.wordpress.org/wordpress-3.2.1-ja.zip
$ unzip wordpress-3.2.1-ja.zip 
$ cd /var/www/html/
$ cp -r ~/work/wordpress sample.com
$ chown -R apache:apache sample.com
$ cd sample.com
あとは、サイトにアクセスして画面の指示通りに進めるだけ。
この後、導入しているネットワーク監視システム Xymonから、メモリ不足の警告メールが。

予め、予想されていたので、本当はApacheから nginx (エンジンエックス)にWebサーバを変更することも考えていたのですが、先ずは APCを試してみることにしました。
注) 私は、PHP, mysql を remi リポジトリからインストールしているので、下の例のように apcも、remi指定のインストールです。
$ yum install php-pecl-apc --enablerepo=remi
$ /etc/init.d/httpd restart

導入効果は中々のもの。その間のメモリ状況のグラフを以下に表示します。

* 9/30 0時頃にメモリ不足
* その後、すぐにAPCを導入
* 9/30 早朝に画面を撮る