R5 reference class覚え書き

R2.12から実装されたR5クラスの覚え書きです。日本語の情報はまだないみたいなので一番乗りを狙って。ちなみに継承関係は、面倒なので完全に無視してます。ごめんなさい。その他、網羅性は期待しないでください。

R5クラスの特徴

  • 参照渡し
  • オブジェクトを編集できる
  • S4より緩くて使いやすい

他にもあると思いますが、触ってみた感想ということで。

とりあえずクラス定義

tc <- setRefClass(Class="testClass",
        fields = list(f1="numeric", f2="numeric"),
        methods = list(
          foo = function() {
            "f1とf2を足し合わせるメソッド"
            f1 + f2
          }))

R5クラスはsetRefClass()で定義します。主に使うオプションは、Classとfieldsとmethodsです。Classでクラス名を定義します。fieldsにはオブジェクトの持つフィールドの名前を文字列ベクトルかリストで定義します。リストの場合は、list(名前="クラス",...)という形で、フィールドのクラスを定義します。リストを使ってフィールドのクラスを定義した場合、オブジェクトの作成時に型チェックが行われます。型が合わない場合はエラーではなく強制変換されます。たとえ強制変換の結果がNAであっても(警告は出るものの)オブジェクトは生成されるので、注意が必要です。文字列ベクトルで定義した場合は当然型チェックは行われません。methodsにはメソッドをリストで定義します。関数定義の一行目に文字列を書くと、メソッドのヘルプと認識されます。メソッド内では、フィールドに定義した変数を自由に使うことができます。

setRefClass()はgenerator objectを返します。generator objectは、オブジェクトを生成したり、メソッドをクラスに追加するときなどに使います。ちなみにgenerator objectもR5クラスです。

generator object

generator objectはクラスを管理するために使われるので、結構重要です。

test <- tc$new(f1=1, f2=2)
tc$accessors("f1", "f2")
tc$help(foo)
tc$methods(
  bar=function(x){
    f1 <<- f1 + x
  })

前述のとおり、generator object自身もR5クラスなので、各種メソッドを持っています。R5クラスのメソッドは、オブジェクト$メソッド(...)という形で使います。1行目は、newメソッドでオブジェクトを生成しています。accessorsメソッドは、フィールドのgetterとsetterを自動的に定義してくれます。これを実行すると、getF1、setF1、getF2、setF2というメソッドが追加されます。helpメソッドは、メソッドのヘルプを見るためのメソッドです。methodsメソッドは、引数なしで実行した場合はメソッドの一覧を表示します。上の例のようにすれば、メソッドを新たに追加することができます。ちなみに、例のようにメソッド内で<<-を使うことで、フィールドを上書きすることができます。

オブジェクトをいじってみる

> test$foo()
[1] 3
> test$bar(10)
> test$getF1()
[1] 11
> test$foo()
[1] 13
> test$setF2(5)
> test$foo()
[1] 16

その他重要なこと

  • initializeメソッドはオブジェクトを生成するときに実行される
  • finalizeメソッドはガベージコレクションによってオブジェクトが消去される前に実行される
  • メソッド内で、.selfはオブジェクト自身を意味する
  • R5クラスオブジェクトを参照渡しでなくコピーしたいときは、copyメソッド

gnupack 4.08aでessが起動できない。

gnupack 4.08aでessのロケールの問題は解決されたのですが,そもそも起動ができません。
gnupackのconfig.ini内のSHELL=/usr/bin/bashをSHELL=bashにすることでいちおう回避はできました。
ただ,そもそも4.08aでのバグフィックスとしてSHELL=bash→SHELL=/usr/bin/bashに変更になっているので,根の深い問題なのかもしれません…。

追記:
作者さんに問い合わせたところ,適切な対応策を教えていただけました。
SHELL = %CYGWIN_DIR%/bin/bash
と書いておくのがよいようです。次期リリースでこの修正を適用していただけるそうです。感謝。

WindowsでEmacs+ESSでlocaleが設定できない問題の解決方法

追記:この問題は,gnupack4.08aでは起きません。ただし,別の問題が発生しています

id:Rion778さんがWindowsでのESSの設定について素晴らしい記事を書いてくれました。

http://d.hatena.ne.jp/Rion778/20100920

僕もgnupackを使っているのですが,再インストールを繰り返しているうちに設定がめんどくさくなって放置しています…。

さて,id:Rion778さんがヘルプを出されている点について,以前同じところでつまずいて,解決できていたような気がしたので(しかしその方法は放置している間にすっかり忘れていた)記事にしておきます。

ところでこれまでの方法で設定するとR起動時に「起動準備中です - 警告メッセージ: Setting LC_CTYPE=ja_JP.cp932 failed」などと出たうえ、plotなどでR Graphicsデバイスを呼び出したときにメニューが文字化けしてしまうので誰か助けて下さい><

これはどうもこの問題のようなのですが,何をいっているのかさっぱりわかりません。Sys.setlocaleが失敗することがあるという問題のようです(そしてRのバグではなくWindowsの問題らしい)。ESSのパッチを提供するのがスマートなんだと思いますが,LISPわかりません。とりあえずその場しのぎの解決策です。普通に

Sys.setlocale(locale="CP932")

とやってもエラーが返ってきます。いろいろと試してみたところ,

Sys.setlocale(locale="Japanese")

もしくは

Sys.setlocale()

でlocaleを変更できました。後者ですが,引数localeの初期値は""(空の文字列)となっていて,そのまま実行すると,システムのデフォルトのlocaleを設定する,という動作になる,とhelpに書いてました。下の二つのどちらかを.Rprofileに書き足しておけば毎回自動で設定されます。Sys.setlocale(locale="Japanese")のほうが安全かもしれません。

あと,僕の環境ではinit.elに以下の設定が必要でした。

(setq ess-pre-run-hook
  '((lambda () (setq default-process-coding-system '(cp932 .   cp932))
   )))

memiscGUIアップデート(リコード機能,ログ機能追加)

リコード機能とログ機能を付けました。

追記

リコードのrange記法を追記しました。

リコード機能

変数上で右クリックしてリコードを選択すると,リコードのダイアログが表示されます。
f:id:phosphor_m:20100703214904p:image

一番上がその変数に存在している値です。その下の左側が変数の値とラベルの対応関係です。この二つを分けている理由が一見分からないかもしれませんが,ラベルは存在していない値にも付けることができ,反対に値は存在するがラベルはついていない場合があるので,そういったことを確認するためにこうこう構成にしています。

ラベルの欄の右側ついては,一番上がいまリコードしている変数の名前,その下がリコード結果を保存する変数の名前です。リコード先にリコード元と同じ名前,またはデータセット中に存在する変数名を入力すると,上書きされます。データセット中に存在しない変数名を入力すると,新変数として付け加えられます。

その下の「テンプレートの生成」ボタンを押すと,その下にリコードのテンプレートが生成されます。基本的に,これを書き換えてリコードすることになります。下の画像が実例です。
f:id:phosphor_m:20100703214905p:image

この例では,1は1のまま,2と3を2に統合して「中」というラベルを付ける,4と5を3に統合して「下」というラベルを付ける,その他の値はそのまま,というふうになっています。

otherwiseはこの例では意味がありませんが,リコードを指定していない「その他の値」についての処理を記述します。例えば一行目の1の値については,otherwise="copy"を指定しているので,今回の場合消してしまっても同じ結果になります。otherwise=NAにすれば「その他の値」は欠損値になりますし,otherwise=3とすれば「その他の値」はすべて3になります。

量的変数をカテゴリ変数にリコードしたい場合,range記法が便利です。

"低"=1 <- range(min , 40),
"中"=2 <- range(40.01, 60),
"高"=3 <- range(60.01, max)

このように書くと,最小値から40までが1でラベル「低」,40.01から60までが2でラベル「中」,60.01から最大値までが3でラベル「高」というふうにリコードされます。値を重複させるとエラーになるので気をつけてください。

基本的な書き方はmemiscパッケージのrecode()関数と同じです。詳細はそちらを参照してください。

ログ機能

データセット選択のドロップダウンメニューの右側に,「スクリプト」というボタンがあります。これをクリックすると,実行した操作のログを見ることができます。
f:id:phosphor_m:20100703214906p:image
変数に対する操作は,変数名の変更を除き,すべて記録されます。変数名の変更のログについては,実装上で迷っていることがあって,今回省きました。

このログは,データセットごとに分けて記録されます。また,一時環境中にデータセットとともに保存されているので,一度memiscGUIのウィンドウを閉じてしまっても,再度起動すれば見ることができます。


ダウンロードは下のリンク先から。

http://d.hatena.ne.jp/phosphor_m/20100628/1277718761

Shiga.R #NA 発表資料

Shiga.Rに行ってきました。発表もさせてもらったので,資料を上げておきます。

普通に生活していては絶対に出会えない方々と話ができて,とても楽しかったです。

理系の,しかも同年代じゃない人なんて,そもそも知り合いが親族ぐらいしかいないということに気づいて,狭い世界で生きてるんだな,ということを実感しました。

自分の研究生活にとっても,普段関わる方々からはおそらく聞けないであろうアドバイスをもらえたりして,自分のネットワークの外へ出て行くのは非常に重要なことだということにいまさらながら気づきました。

ラノヴェッターの弱い紐帯理論の妥当性をひしひしと感じて,これほど腹に落ちる社会学理論って希有だな,と思ったり。

memiscGUIパッケージの使い方

インストールはこちらで

起動

インストール後,起動は以下のようにするだけです。

library(memiscGUI)
memiscGUI()

f:id:phosphor_m:20100628190511p:image

データの読み込み(ファイルから)

起動すると,上のようなWindowが表示されます。メニューバーのファイルをクリックすると,次の画像のようなメニューが出てきます。
f:id:phosphor_m:20100628190512p:image

まずは,インポートを選んでファイルを読み込んでみます。現在のところ読み込めるのはSPSSシステムファイル(*.sav),SPSSポータブルファイル(*.por),Stataファイル(*.dta)です。読み込む形式を変えたいときは,右下のドロップダウンメニューから選んでください。
f:id:phosphor_m:20100628190513p:image

大きなデータだと読み込みに時間がかかると思います。読み込みが終わると,以下のようにWindowの表示が変わります。
f:id:phosphor_m:20100628190514p:image

値ラベル以外は,行を一度選択してから,次に各セルをクリックすると編集できます。尺度はドロップダウンメニューが出てきます。欠損値は,欠損値に指定したい数値をコンマで区切って入力してください。

行にカーソルを合わせると,変数のsummaryがポップアップします。行をダブルクリックすると,より詳しい要約がコンソールに表示されます。これはmemiscパッケージのcodebookという関数を使っています。
f:id:phosphor_m:20100628190515p:image

複数データを読み込んだ場合も,手軽に切り替えることができます。
f:id:phosphor_m:20100628190516p:image

作業環境からのデータの読み込み

「大局的環境からのインポート」では,すでに作業環境にあるデータをmemiscGUIに読み込むことができます。読み込めるデータは,data.frameかdata.setです。ドロップダウンメニューから読み込みたいデータを選択してください。
f:id:phosphor_m:20100628190519p:image

data.frameとの関連づけ

データは,memiscGUIから読み込んだ場合,そのままでは利用することができません。Rの作業環境(大局的環境)とは別の環境でデータを管理する仕組みになっているためです。memiscパッケージではdata.frameの高機能版のようなdata.setというクラスでデータを管理するのですが,高機能な分,扱いを覚えなければならなかったり,data.frameと全く同じようには扱えなかったりします。そのため,memiscGUIではdata.setの操作をユーザーの目からは完全に隠蔽し,ユーザーが使うのはdata.frameだけで済むようにしています。

具体的には,memiscGUIの管理しているdata.setを作業環境のdata.frameと関連づけ,data.setへの変更が即座にdata.frameに反映される機能を付けています。メニューバーのファイルから「データセットをデータフレームと結び付ける」を選ぶと,下のようなダイアログが表示されます。
f:id:phosphor_m:20100628190517p:image

左の列がmemiscGUIが管理しているdata.set,右の列が作業環境中でdata.setに関連づけられるdata.frameです。関連づけるdata.frameは,関連づけのさいに存在していなくてもかまいません。ここで関連づけられたdata.frameは,data.setを編集したさいに上書きされます。data.frameへの上書きは変数単位ではなく,まるごと上書きされるようになっているので,注意してください。逆に,data.frameの編集はdata.setには影響を与えません。関連づけは常にメイン画面で確認できるようになっています。
f:id:phosphor_m:20100628190518p:image

上級編

データはmemiscGUIのパッケージ環境内にある.memiscGUI.envという環境オブジェクト内で管理しています。.memiscGUI.envに直接アクセスすることで,data.setオブジェクトを取り出すことができます。

> ls(envir=.memiscGUI.env)
[1] "JIS2001_040219_sav"                   
[2] "JIS2002_030603_sintax_040223_area_sav"
[3] "JIS20041012_sav"
> ds1 <- .memiscGUI.env$JIS2001_040219_sav

また,データを自分で作った環境オブジェクト内で管理することもできます。

data.env <- new.env()
memiscGUI(envir=data.env)

こうすることで,データをひとまとめにせず,分類して管理できます。また,環境オブジェクトを保存しておいて,次回起動時に使い回すという使い方もおすすめです。この操作はそのうちGUIでできるようにしようと思っています。

感想・要望・不明な点等

これで一通りの機能を説明したと思います。感想・要望・不明な点等あれば@phosphor_mかコメントでよろしくお願いします。

SPSSからの乗り換えに―memiscGUIパッケージ

Osaka.R #3で発表したmemiscGUIパッケージの紹介です。

memiscパッケージの詳細についてはこちらのスライド(PDF)を参照していただきたいのですが,SPSSの変数名ラベル,値ラベル,ユーザー欠損値などの機能がRでも使えるようになるパッケージです。

memiscGUIパッケージは,なんのひねりもない名前ですが,memiscパッケージの機能をGUIで扱えるようにするためのパッケージです。ようは,memiscパッケージの力を借りて,エセSPSSをR上で作ることを目指したものです。

以前DFBrowserという似たようなパッケージを作っていましたが,そのころはmemiscパッケージの機能を把握していなかったため(存在は知っていた),値ラベルやユーザー欠損値といった機能はありませんでした。後日無理矢理組み込もうとしたんですが,DFBrowserの作成当初はバックエンドとして用いているRGtk2の扱いが全くわかっていなかったため,場当たり的なコードが多くて改造が困難で,挫折していました。

memiscGUIは,DFBrowserの経験をもとに一から作っています。部分的に流用できるコードはかなりあったので,基本的な実装は意外と早く(3〜4日ぐらい)できました。分析機能やエディタ機能は省き,データ管理機能の作り込みに注力しています。SPSSとRを使い分けている方は,データ管理はSPSS,分析はRというパターンが多いみたいなので,まずデータ管理機能がSPSSと同等になれば,そういう方はSPSSを捨てられるだろうという魂胆です。データ管理機能が満足行くものになれば,分析機能も作るかもしれません(別パッケージにするかもしれませんが)。

インストール

前置きが長くなりましたが,まずインストール方法から。必須パッケージはRGtk2とmemiscです。どちらもCRANからインストールできます。ただし,RGtk2用にGtk2をインストールする必要があります。Windowsの場合は,RGtk2パッケージをインストールした後,library(RGtk2)でRGtk2パッケージを読み込むと,Gtk2をインストールするかどうか尋ねられるので,指示に従ってインストールしてください。インストール後,Windowsを再起動すると,RGtk2パッケージが使えるようになっています。Macの場合も同様だった気がします(確認は取れていません,どなたか確認が取れたら教えてください)。LinuxではたいていGtkは入っていると思いますが,libgladeをインストールする必要があるかもしれません。あとはmemiscGUIパッケージをインストールするだけです。

最新版
前バージョン

Windowsの場合は,Windows用バイナリをダウンロードして,メニューバーから「パッケージ>ローカルにあるZIPファイルからのパッケージのインストール」を選んでインストールしてください。いずれCRANに載せたいと思っていますが,英語でヘルプを書くのがめんどうなので…。ちなみに国際化に対応しています。これもこのパッケージの目玉機能です。

起動は,library(memiscGUI)で読み込んだ後,memiscGUI()を実行するだけです。使い方は次の記事で。

追記

Macでは動作確認ができていません。pure Rなのでたぶん動くのですが,Gtkの動作がプラットフォームによってやや違うこともあるので保証はできません。

Linuxは,Ubuntu 10.04で動作を確認しました。ただし,データの読み込みに難があります。SPSSのデータを読み込んだ場合,文字コードを変換してくれないようです。これはMacでも共通の問題かもしれません。現在のところ,実質的に,英語のみのデータしか読み込むことができません。大局的環境からのインポートは問題なく動作すると思います。Stataのデータについては未確認です。