はじめに
Hadley Wickham著「R言語徹底解説」を訳者の方よりご恵贈いただきました.ありがとうございます!御礼と宣伝,また自分の復習をかねて,紹介記事を書きたいと思います.
本書「R言語徹底解説(原著 "Advanced R")」は,著名なR開発者であるHadley Wickhamが,Rの基本的な構造から,メタプログラミングやパフォーマンス改善といった高度な話題に至るまで,プログラミング言語としてのRの全体像を詳しく解説したものです.
2016年の今,データ分析にRを利用しているという人でggplot2
やdplyr
といったパッケージを知らない人はいないでしょう.本書の著者Hadley Wickhamはこれら広く利用されているパッケージの開発者です.githubを見れば分かる通り,著者は現在RStudioに所属しており,上に挙げたような著名なパッケージを始めとする数多くのRパッケージ開発に日々取り組んでいます.
また,執筆活動も精力的に行っており,本書の他にも「グラフィックスのためのRプログラミング(原著 "ggplot2")」や「Rパッケージ開発入門(原著 "R Packages")」が出版されています.(ちなみに,原著はいずれも現在ウェブで無料公開されています:Advanced R,R Packages,ggplot2).さらにGarrett Grolemundとの共著で
"R for Data Science"という本も執筆中のようです.
要するに,著者は開発者としての実績とライターとしての経験を兼ね備えており,Rについて解説するのにこれ以上ふさわしい人は他にいないと言えるでしょう.
優れた著者によって書かれた本書の内容は他に類のない貴重なものになっています.Rを利用して統計分析・機械学習やデータの可視化を実践するための応用的な解説書は既に数多く出版されていますが,本書はそれらとは異なり,プログラミング言語としてのRに焦点を当てて体系的に解説しています.すぐに役立つパッケージの紹介などはありませんが,良いコードを書きたい人や,単なるユーザを脱して自分でもパッケージを作りたい人にとって必要なRプログラミングの知識と技術が広く深く解説されています.今後Rの上級者を目指す人にとっては必読書となりそうな一冊です.
本書は導入的な1章と「基本編」,「関数型プログラミング」,「言語オブジェクトに対する計算」,「パフォーマンス」の4部に分かれた全20章で構成されています.以下,簡単に各章の内容を紹介していきます.
導入
1章は導入のための短い章ですが,Rの魅力と,Rユーザの多くがプログラマでないがゆえの困難について,著者の見解が書かれているのが印象的です.Rに様々な問題があるからこそ,Rユーザのスキル向上と他言語のプログラマからの貢献を期待して本書を書いたことが述べられています.
ところで,推奨文献に有名な
- H. Abelson, G. J. Sussman, 「計算機プログラミングの構造と解釈」
- P. van Roy, S. Haridi, 「コンピュータプログラミングの概念・技法・モデル」
が挙げられているのですが,やはりデータ分析者であっても読んでおいた方がよいのでしょうか…….
第I部 基本編
2章の「データ構造」と3章「データ抽出」ではベクトル・リスト・データフレームといったデータ構造と,[
や[[
や$
などのデータ抽出演算子について解説されています.基本的な内容ですが,つまずきやすい細かい点や謎の仕様について分かり易くまとめられていて便利です(stringAsFactors
の話など).
4章「ボキャブラリ」では,Rを使いこなすために押さえておきたい,base
,stat
,utils
パッケージの重要な関数が列挙されています.意外と使ったことのない関数があったので読んでいて焦りました.
5章「コーディングスタイルガイド」は名前の通りです.Rでの推奨コーディングスタイルが簡潔にまとめられています.Hadleyは付値は<-
派のようです.
6章「関数」からがいよいよ本番という感じです.Rで単純な関数を作って使うのは簡単ですが,関数とは正確には何なのか理解するのはそれなりに大変です.本章ではレキシカルスコープ,遅延評価,純粋関数やコピー修正(copy-on-modify)セマンティクスといった,関数の理解にとって重要な概念が説明されます.色々な概念や機能が簡潔なコード例とともに次々に導入されていくので,この章だけでは理解が難しいところも多いですが,8章「環境」や第II部,第III部を読み進めていくうちに理解が深まります.少なくとも,本章で引用されているJohn Chambersの言葉だけでも覚えておくとRの挙動を考えるときの見通しが良くなるように思います.
- すべてはオブジェクトとして存在する.
- R内で起きることすべては関数呼び出しである.
7章では,S3,S4,RCの3種類もあることで有名な(悪名高い?)Rのオブジェクト指向システムについて解説されています.最も基本的なS3については詳しく説明されていますが,S4とRCの解説は意外とあっさりしています.ほとんどの用途ではS3で事足りるというのが著者の見解のようです.
また,本書では扱われていませんが,shinyなどのパッケージを見ると,RStudioではR6という独自に実装した新しいオブジェクト指向システムがよく使われているようです.
8章「環境」は非常に重要な章です.環境はRにおける変数のスコープを理解するために必須の概念であり,また第III部で解説される非標準評価のような進んだテクニックを理解するためにも必要なものです.それにもかかわらず,他書ではほとんど説明されることがないように思います.parent.frame()
とか見たことはある気がするけど何なのかよく分からないという人(本書を読む前の私ですが)はぜひとも本章を読んで理解を深めましょう.
9章ではデバッグとエラー処理が扱われています.個人的にはRでtryCatch()
などのエラー処理機能を使う機会はあまりないのですが,実はRのエラー処理機構は機能が結構充実していることを知って驚きました.
第II部 関数型プログラミング
10章から12章では関数型プログラミングが扱われます.はじめの10章では,関数を活用することで簡潔で汎用性があり,保守しやすいコードが書けることが簡単な具体例で示されます.また無名関数やクロージャといった基本的な概念が説明されています.
11章は関数を引数にとる関数,つまり汎関数についての解説です.apply()
系関数やMap()
,Reduce()
,Filter()
といった関数についての説明が詳しいですが,これらの関数を使わずループを使うべき場合についても述べられており,バランスの取れた解説になっています.
12章は関数を引数に取って関数を返す,関数演算子の解説です.関数演算子を利用すると,関数の入出力をカスタマイズしたり,関数を合成して新しい関数を作成したりといった複雑な処理が非常に簡潔なコードで実現できるようになることが分かります.
ちなみに,本書では扱われていませんが,著者は現在Rの関数型プログラミング機能を強化するpurrr
パッケージを開発しており,Rの関数型プログラミングはこれからさらにおもしろく,便利になっていくものと期待しています.
第III部 言語オブジェクトに対する計算
第III部はRの言語そのものに対する計算,いわゆるメタプログラミングについての解説と,その応用です.おそらく本書の中で最も難しく,かつ興味深いRの特徴を扱った箇所だと思います.
言語に対する計算と聞くと何だか難しそうですが(そして,私も実際難しいと思いますが),実はRユーザであれば日常的にその恩恵に浴しているものです.Rユーザならlm(y ~ x, df)
やsubset(df, x == y)
といった関数を使っていて「いちいちdf$x
などと書かなくて済むのは便利だけど,この関数はどうやって実装するんだろう?」と思ったことがあるのではないでしょうか.
これらの関数を実装するための手段が言語に対する計算を通じた「非標準評価」であり,13章ではsubset()
関数の実装を通してこれを学ぶことができます.
続く14章「表現式」ではさらに深くRの言語構造とその操作方法について解説されます.ここが読めればRの中からRの構文木がいじり放題です.最後の15章では応用として,HTMLを生成するドメイン特化言語や,Rの表現式をLaTeXの数式に変換するドメイン特化言語を作成します.
第III部の内容は私自身まだ十分に消化しきれていないので,本書やRのソースコードを読んで,自分でも活用できるようになるまで理解を深めたいものです.
第IV部 パフォーマンス
第IV部の16章~20章はRのパフォーマンス特性の解説と,パフォーマンス改善のテクニックに充てられています.
最初の16章はRが遅い原因の全般的な説明です.「究極的な動的特性(extreme dynamism)」というR言語の設計自体に起因する点と,GNU-Rの実装のまずい点に分けて説明されています.Rコアチームは20人いるけど日常的に開発しているのは6人だけで,しかも大学教員ばかりなのでフルタイムでは開発できない,という話が書かれているのが悲しみを誘います.著者もGNU-Rのパフォーマンスがなかなか改善されないことにはだいぶフラストレーションを溜めてきたようです.章末ではGNU-R以外の代替実装も簡単に紹介され,今後のR開発への期待が述べられています.
17章「コードの最適化」ではプロファイリングのやり方から始めて,最適化のための一般的な考え方や
ベクトル化・並列化・バイトコードコンパイルといったテクニックが一通り説明されます.最後の手段(?)のRcpp
については19章で1章を割いて解説しています.
18章はメモリ管理についてです.メモリ使用量の調べ方に始まって,Rのオブジェクトの構造やガベージコレクタなどについて説明されています.コピー修正(copy-on-modify)と即時修正(modify-in-place)の説明のところで,for
ループが遅いのはループ自体が特別に遅いのではなく,ループのたびにオブジェクトをコピーするから遅いのだという話は,今まであまり意識していなかったので啓発的でした.
19章はRcpp
の話です.Rcpp
自体の説明はもちろん,C++についても最低限の基本事項と便利なSTLに絞って解説がなされており,C++の知識がない人にもすぐに役立てられる内容になっています.
大抵の人間には生きている間にC++の全貌を把握する時間がないと思われるので,こうしてスモールスタートできるのはありがたいです.私もC/C++は学生の頃に少し書いたきりですっかり忘れていましたが,データ分析の中で使えるところを探してまた使いたくなってきました.
最終章である20章ではRとC言語のインターフェイスについての解説です.既にRcpp
について前章で解説しているので,本章はパフォーマンス向上のためのテクニックというよりは,RのC言語で書かれた部分に対する理解を深めるための内容になっています.SEXP
のことが何となく分かった気になれます.
おわりに
以上,本書の内容を振り返ってざっと紹介してみましたが,改めて内容の豊富さを実感しました.私自身,理解しきれていないところも多く,エクササイズなども飛ばしているので,これからまた読み返して手を動かすことになりそうです.
最後に翻訳についてですが,けっこう分厚い本で共訳にもかかわらず,ストレスなく読める統一感のある訳になっていると感じました.また,プログラミング関係の用語や最新バージョンのRでの更新事項等について適宜訳注で補足されています.原著がウェブで読めるとはいえ,やはり読み返したり人に薦めたりするには日本語版があるのは便利でありがたいですね.