Incanterを今からはじめるなら

IncanterはLISP+R on JVMという理想環境

Incanterは「Clojureで動くRっぽい雰囲気の統計環境」とのことで、けっこう期待しているんですが、このところ表立った動きが見えてこないので寂しいです。JVM上でLISPを使って統計ができるのだから最強だと思うんだけどなぁ。(何ができるのか概要を知るためには『統計解析アプリ「Incanter」入門 - あんちべ!』や『Web系女子がLispと出会って統計学に目覚めるまでのお話 - あんちべ!』が良いと思います)

で、本家サイトのトップページで「最新ビルドをダウンロード」みたいなところからダウンロードするとバージョン1.2.xのバイナリパッケージが入手できます。ただ、GitHubで行われている開発版を見てみるとバージョンは1.5.xで、すでに1.2の頃から大分と変更がなされているようです。最新版をできるだけ簡単に使うにはHomebrewが良いのではないかと思うので、Incanterを使いはじめる方法とか書いてみますね。

IncanterをLeiningenから使う

ここではHomebrewがすでにインストールされているとします。まず、Leiningenのインストールをします。これはMavenClojure版という説明がされていることが多いですが、プロジェクト管理システムです。プロジェクト定義ファイルに必要なライブラリを書いておくと自動的にダウンロードしてくれたり便利です。

$ brew install leiningen

Leiningenを使ってプロジェクトを作成します。

$ lein new incanter-test
$ cd incanter-test

プロジェクト内のproject.cljという定義ファイルに一部修正を加えます。以下のように、最後に「Incanterのバージョン1.5.4を使用しますよ」という依存情報を1行だけ書き加えます。

(defproject incanter-test "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [
                 [org.clojure/clojure "1.5.1"]
                 [incanter "1.5.4"]])

以下のようにLeiningenからREPLを実行すると、すぐにIncanterが使える状態になります。初回は自動的に依存パッケージなどをダウンロードしてくれますのでゴチャゴチャと出力されますが、二回目以降は以下のようなかんじになります。

$ lein repl
nREPL server started on port 49997 on host 127.0.0.1
REPL-y 0.3.0
Clojure 1.5.1
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)
 Results: Stored in vars *1, *2, *3, an exception in *e

user=> 

実行してみる

まずIncanterを使うための準備をします。ライブラリの読み込みですね。

user=> (use '(incanter core stats charts io datasets))

わからない関数などがあったら(doc hoge)とするとドキュメントが表示されます。

user=> (doc use)
-------------------------
clojure.core/use
([& args])
  Like 'require, but also refers to each lib's namespace using
  clojure.core/refer. Use :use in the ns macro in preference to calling
  this directly.

  'use accepts additional options in libspecs: :exclude, :only, :rename.
  The arguments and semantics for :exclude, :only, and :rename are the same
  as those documented for clojure.core/refer.
nil

おなじみフィッシャーのirisデータを使ってみましょう。ここでも(doc get-dataset)とすると、最初からIncanterに含まれている代表的なデータが表示されます。;以降はコメントとして無視されます。以下、一部出力結果を省略しています。

user=> (get-dataset :iris)
user=> (head (get-dataset :iris))    ; ずらずら出るので最初の一部分だけ表示

| :Sepal.Length | :Sepal.Width | :Petal.Length | :Petal.Width | :Species |
|---------------+--------------+---------------+--------------+----------|
|           5.1 |          3.5 |           1.4 |          0.2 |   setosa |
|           4.9 |          3.0 |           1.4 |          0.2 |   setosa |
|           4.7 |          3.2 |           1.3 |          0.2 |   setosa |
|           4.6 |          3.1 |           1.5 |          0.2 |   setosa |
|           5.0 |          3.6 |           1.4 |          0.2 |   setosa |
|           5.4 |          3.9 |           1.7 |          0.4 |   setosa |
|           4.6 |          3.4 |           1.4 |          0.3 |   setosa |
|           5.0 |          3.4 |           1.5 |          0.2 |   setosa |
|           4.4 |          2.9 |           1.4 |          0.2 |   setosa |
|           4.9 |          3.1 |           1.5 |          0.1 |   setosa |

user=> (def iris (get-dataset :iris))    ; irisという名前をつける
user=> ($ :Sepal.Width iris)   ; $を使うと一部だけとり出せる
user=> (sel iris :cols [1 2])   ; selも似ている
user=> (def sw ($ :Sepal.Width iris))    ; がくの幅と、
user=> (def sl ($ :Sepal.Length iris))    ; がくの流さをとりだして、
user=> (view (scatter-plot sw sl))    ; 散布図を表示する

f:id:amarui:20140215133345p:plain

さて、ここから主成分分析をして結果を見てみましょう。((doc principal-components)で出てくる例と同じですが。)

user=> (principal-components (sel (to-matrix iris) :cols (range 4)))   ; 主成分分析
{:std-dev (1.7083611493276223 0.9560494084868574 0.383088600158391 0.1439264966176126), :rotation  A 4x4 matrix
 -------------
-5.21e-01 -3.77e-01  7.20e-01  2.61e-01 
 2.69e-01 -9.23e-01 -2.44e-01 -1.24e-01 
-5.80e-01 -2.45e-02 -1.42e-01 -8.01e-01 
-5.65e-01 -6.69e-02 -6.34e-01  5.24e-01 
}
user=> (def pca (principal-components (sel (to-matrix iris) :cols (range 4))))    ; あとで参照するために主成分分析の結果に名前をつける
user=> (keys pca)    ; pcaにどんなキーが入っているか見る
user=> (def pc1 (sel (:rotation pca) :cols 0))    ; 0列目と1列目の主成分負荷量を取り出す
user=> (def pc2 (sel (:rotation pca) :cols 1))
user=> (def x1 (mmult (sel (to-matrix iris) :cols (range 4)) pc1))    ; 主成分得点を計算
user=> (def x2 (mmult (sel (to-matrix iris) :cols (range 4)) pc2))
user=> (view (scatter-plot x1 x2
         :group-by (sel iris :cols 4)
         :x-label "PC1" :y-label "PC2" :title "Iris PCA"))    ; 結果を散布図に表示

f:id:amarui:20140215134547p:plain

ここから?

冒頭にも貼ったあんちべさんのサイトに書かれているClojure/Incanterの記事がかなりいかしているので、そちらをぜひ参照してください。他にも英語だけど下のあたりが参考になりそう。