東京r非公式おじさんが教える本当に気持ちいいパッケージ作成法
DESCRIPTION
Presentation document in TokyoR#42.TRANSCRIPT
東京. 非公式おじさんが教える本当に気持ちイイ
パッケージ作成法 with Studio
第42回 勉強会@東京(#TokyoR)
@teramonagi
もくじ • 1:パッケージ開発環境の準備 • 2:パッケージ開発ハンズオン
–2-1:動くものを作る –2-2:パッケージの配布について –2-3:テストの追加
• 3:その他アレコレ –3-1:C++で機能追加 with Rcpp –3-2:vignetteの作成 with knitr –3-3:おまけ
• 4:参考 2
1:パッケージ開発環境の準備
3
のパッケージ?
のパッケージ
||
の拡張機能を提供
4
パッケージにも開発者がいる!!!
5
今までの僕らは、与えられた者を使う側の人間。いい加減、与える側に回りたいよ
But… 6
(かつてのパッケージ開発環境)
7
無茶しやがって…
8
今は ♥♥♥HEAVEN♥♥♥
9
ある漢の活躍
10 ※まだ生きてるつーか、現役バリバリです
パッケージ開発のための パッケージ
• devtoolsパッケージ
–開発を楽にする
• roxygen2パッケージ
–Doxygenライクなin-sourceドキュメント生成
• testthatパッケージ
–単体テスト作成・実行
11 Welcome to Hadley world!!!
開発者:Hadley wickham
12
まさに神(Hadley)が与えし
三種の神器
おまけ:神を で描画するコマンド
13
library(ggmap)
library(magrittr)
hadley %>% ggimage
パッケージ開発のための パッケージ
•三種の神器をインストール
14
install.packages(“devtools”) install.packages(“roxygen2”) install.packages(“testthat”) ※できればGithubあたりから開発版入れた方がいいかも
使用する外部ツール/サーヴィス
• MUST
–Rstudio(Rの統合開発環境)
• WANT
–Rtools(主にC++ compiler for windows)
–Git(ゆるふわなTortoiseGitで…)
–Github(パッケージの共有用)
• 各々のインストール方法はggrks 15 ※漢(おとこ)は黙ってOS is Windowsを想定
2:パッケージ開発ハンズオン
16
パッケージ開発ハンズオン
• OpenWeatherMapが提供するAPIを叩くパッケージ開発
17 ※ http://openweathermap.org/より
2-1:動くものを作る
18
動くものを作る(目標)
•その他条件
–インストール可能なものを作る
–警告0でチェックが通るようにする
–出来るだけMinimumなものを作る
–CRANへのUPは闇なので、放置
(最近はGithubでいんじゃね?感ある)
19 ※ここでは、「チェック」とは「Rのパッケージとして正しく動作するか否かをチェック」すること
よろしい、 ではスタートだ!!! 20
Studioを起動してポチポチ…
• [File]→[New Project]を選択
21
• [New Directory]→[R Package]と選択
22
Studioを起動してポチポチ…
※ふつーのRコード書く際にも常に[Empty Project]使っておくのがよい
パッケージの作成
• [Package name]入力,gitも出来れば
23 ※ここではrOpenWeatherMapとした。以下、適当に自分のパッケージ名に読み替える
雛型完成
24
…からの不要ファイル削除
•以下は不要なファイルなので削除
–Read-and-delete-me
–man/rOpenWeatherMap-package.Rd
• その他のファイルは
–そのまま使用
–roxygen2の自動生成で上書き
なので放置でOK 25
大雑把なフォルダ/ファイルの説明 • DESCRIPTION
– パッケージの概要&他パッケージへの依存を書く • NAMESPACE(ここではroxygen2で自動生成させる)
– どの関数をパッケージ外から使うか記述(含む他ライブラリ) • manフォルダ
– .Rd形式のマニュアル(ここではroxygen2で自動生成させる) • Rフォルダ
– 自分で書いたRのコードを突っ込む • XXXignore
– git/githubに対して監視させない無視させるファイルを設定 • XXX.Rproj
– Rstudio用の設定ファイル。テキストベースなので適当なエディタでも編集可能
26 ※赤字ファイル/フォルダを手でいじる、他は自動/GUIから設定
Studioのオプション変更
27
• [Tools]→[Project Options]→[Build Tools]
※パッケージ構築(ビルド)の環境を整える
Studioのオプション変更
28
--no-manualでPDF版 マニュアルの生成回避
※CRANにパッケージをUPすれば勝手に作ってくれるので、通常いらないと言えばいらない ※PDF版マニュアルが欲しい場合はTex(TexLive?)のインストールが必要。がんばれ。
roxygen2の設定
29
roxygen2でDocument自動生成ON
roxygenでどのファ
イルを自動生成するか
どのタイミングでファイルを自動生成するか
※何も考えずに全部チェックでもOKかと
DESCRIPTIONファイルを修正
30
警告回避のため Licenseは書換MUST
内部で使用するパッケージはImportsに記載しておく
※Imports/Dependsを書いておくと、CRANからinstall.packagesした時に、その他のパッケージも勝手にインストールしてくれる。Dependsの方は、自作パッケージを読み込むと自動でDependsに指定したパッケージまで読み込んじゃう。一方、Importsの場合、自分で作ってるパッケージ内のみで指定したパッケージが使われるように良きに計らってくれる。依存関係という意味で、Dependsは「XX以降のRじゃないとだめですよ~的な」Rのバージョン指定にのみ使われてるパッケージが結構ある on CRAN
31
次に のコード書く
のコードを書く • [R/currentWeather.R]として以下を追加
32
※RcurlのgetURL関数でAPI叩いて、それをrjsonのfromJSONでリストにしてるだけ ※関数の引数にデフォルト引数与えるとDocumentが自動生成できない…って githubでissueは出しておいた。一応LC_CTYPEロケールをCにすればいけることは確認済
のコードを書く • [R/currentWeather.R]として以下を追加
33
一行目に関数の説明を書く。各項目は以下のような意味合いで、 roxygen2パッケージによりHELPが自動生成される際に参照される。 @param:引数の説明 @return:返値の説明 @export:ある場合、この関数をパッケージの
外から呼び出せるようにする。逆にない(書かない)と外から呼び出せない
• [R/ rOpenWeatherMap.R ]として以下を追加
34
のコードを書く
※ここを書いておくと、HELP・NAMESPACEファイルが自動生成される ※パッケージ名.Rにはパッケージ全体の説明、及び“依存ライブラリ”を書くのが一般的ぽい ※“依存ライブラリ“はNAMESPACEが自動生成される時に使われる
• [R/ rOpenWeatherMap.R ]として以下を追加
35
のコードを書く
”package名.R”ファイルにパッケー時の説明を
記述。ここに依存関係やパッケージの説明(roxygen2パッケージにより作成されるHELP用)を書く。NULL必須(これもroxygen2用) @name:パッケージ名 @doctype:”package”で。 @import:中で使用しているパッケージを記述 (NAMESPACEの自動生成に使用される) ※パッケージの依存関係は関数側に書く事も出来るが、 管理しやすいのでこちらのほうが良さげ
パッケージビルド関連コマンド群
• [Build]パネルに用意されている
36
[More]を押下すると出現
パッケージの構築(ビルド) • Build & Reload[Ctrl + Shift + B] –作成と読込(R CMD INSTALL )
• Check パッケージ[Ctrl + Shift + E] –チェック(devtools::check)
• Test パッケージ[Ctrl + Shift + T] –テスト(devtools::test)
• Document[Ctrl + Shift + D] –資料作成(devtools::document)
37 ※[]はキーボード・ショートカット、()は裏で走ってる(と思われる)コマンド ※devtoolsはその他にも関数がたくさんあるので、調べてみるといい
It works!!!
• [Build&Reload]して、関数を実行!動く!
38
It works!!!
• getCurrentWeatherByCityName関数で、現在の東京の天気を取得
39
It works!!! • HELPも出る(?getCurrentWeatherByCityName実行)
40 ※roxygen2パッケージがコメントとして書いた部分から自動で作ってくれる
パッケージのチェック
• [Check Check]も警告0で通る
41
これで貴方も の パッケージクリエーター!!!
42
ここまでのコード
43
https://github.com/teramonagi/rOpenWeatherMap/tree/First
※DESCRIPTION のLicenseが[MIT + file LICENSE]じゃなくて[MIT]になってます…要修正 ※githubとmergeするときにREADMEとLICENSEファイルが追加されてしまってます
まとめ
1. 三種の神器をインストール
2. Studioからプロジェクト作成
3. 不要なファイルを削除
4. プロジェクトのオプション変更
5. DESCRIPTIONファイルの変更
6. のコードを書く&コメントを付ける
7. [Build&Load]で完成 44
2-2:パッケージの配布について
45
ユーザに配達するまでが
パッケージ開発 46
パッケージの配布法 • Web経由のレポジトリ使っていいなら、基本install.packages関数使うだけで良い
• 一方、そうじゃないケース –ネットワークドライブにソースがどーん –USB/光学ディスク経由
の場合、インストール出来る形式に固めてからそれをインストールする
47
形式:Binary(zip) or Source(tar.gz)
binary(zip)/source(tar.gz)の作成
48
[Build Source Package]→tar.gz [Build Binary Package]→zip をそれぞれ生成
※devtools::build関数が走る
固めたパッケージのインストール
• 固めたものを適当に配る • インストールする側はinstall.packages関数の引数を –repos=NULL –type=“binary” or “source”
としてローカルからインストール
49
#zipの時
install.packages("C:/dev/rOpenWeatherMap_1.0.zip", repos=NULL, type="binary") #tar.gzの場合
install.packages("C:/dev/rOpenWeatherMap_1.0.tar.gz", repos=NULL, type="source")
※パスは自分の環境に応じて適当に読み替える
まとめ 1. パッケージを配布可能なよう固めるために
1.tar.gzの場合:[Build Source Package]
2.zipの場合:[Build Binary Package]
を実行する。
2. インストールは以下のコマンド
1. tar.gzの場合
-install.packages(“固めたファイル", repos=NULL, type=“source")
2. zipの場合
-install.packages(“固めたファイル", repos=NULL, type=“binary“)
50
2-2:テストの追加
51
より良いものを作るためには、 動作確認(テスト)は欠かせない
52
DESCRIPTIONファイルの修正
53
Suggest:にtestthatを指定
※Suggestsはパッケージ本体ではなく、テスト/vignetteのみに使用するパッケージを記載
お決まりフォルダ&ファイルの作成
• Projectフォルダ直下に[tests]フォルダを追加し、そこに[test-all.R]を追加
54
test-all.Rの中身
• 決まり文句を書いておくだけ
–library(testthat)
–test_check(“パッケージ名”)
55
testthatフォルダの追加 • testsフォルダ下に[testthat]フォルダ追加
56
テストファイルの作成
• 今回は[test-currentWeather.R]を作成
57 ※ファイルはどんどん追加してよい
テストコードの中身
58
context("Current weather")
test_that("ByCityName works.", {
place <- "Tokyo,Japan"
current.weather <- getCurrentWeatherByCityName(place)
expect_equal(current.weather$name, "Tokyo")
})
どういうテストの集まりなのかを記述。 通常1ファイル1context
expect_equal中身は等しくなって欲しい ※もっとテストしたい時はtest_thatをどんどん書いてCurrent weather系のテストを増やす
テストの作成。第一引数はテスト名
テストの実行
• Test Package[Ctrl+Shift+T]する
59
60
合ってるの、 これ?
テストコードの中身
• “Tokyo”を”Tokyooooo”にわざと変更
61
context("Current weather")
test_that("ByCityName works.", {
place <- "Tokyo,Japan"
current.weather <- getCurrentWeatherByCityName(place)
expect_equal(current.weather$name, "Tokyooooo")
})
テストの実行
•答えが合わないので怒られる
62
(テスト結果の解釈として)
便りのないのは良い便り 63
パッケージのチェック
•要所要所でチェック!!!
64
まとめ
65
• DESCRIPTIONにSuggests:testthat追記
• testsフォルダを作成し
–test-all.R追加(中身は以下) • library(testthat)
• test_check(“パッケージ名”)
–testthatフォルダを作成し、実際のテスト用ファイル(.R)を作成
ここまでのコード
66
https://github.com/teramonagi/rOpenWeatherMap/tree/Second
3:その他アレコレ
67
若干、趣味に近いお話
68
3-1:C++で機能追加 with Rcpp
69
DESCRIPTIONファイルの修正
70
LinkingTo: Rcppがないとincludeオプション(-I)が正しく指定されない ※当然Rcppはinstall.packagesで使えるようにしておく
srcフォルダにC++コードをおく
71
C++のコードを書く
72
useDynLib化にパッケージ名、importFrom
はこのまま書く。おまじないだと思っておく
.Rファイル同様のコメントをroxygen形式で記述「#’」ではなく「//’」である点に注意
It works!!!
• [Build&Reload]して、関数を実行!動く!
73
※パッケージをビルドするとRcppExports.(R|cpp)が自動生成されて そいつらが勝手に読み込まれる
この辺の試行錯誤記録
• 「@useDynLib パッケージ名」をなくすと… – Error in .Call(“パッケージ名_関数名”, PACKAGE = “パッケージ名”) : “パッケージ名_関数名” not available for .Call() for package “パッケージ名“
でコンパイル通らない。これはDLL/SOを参照するようにしてないため • 「@importFrom Rcpp evalCpp」をなくすと…
– Error in transformSquare(std::vector<double> x) : function 'enterRNGScope' not provided by package 'Rcpp'
でコンパイル通らない。たぶん、Rcppへの参照周りがだめなんだと思う、多分(Rcppのどっかのドキュメントに書いてあったはず)。
• Rcpp系の資料全般、特に以下が参考になった – 「Writing a package that uses Rcpp」
• http://cran.r-project.org/web/packages/Rcpp/vignettes/Rcpp-package.pdf
74
One more 趣味.
75
呪文
• Studioのコンソールに入力
76
Sys.setenv("PKG_CXXFLAGS"="-std=c++0x")
※最近のRcppだと、ソースコード中に // [[Rcpp::plugins(cpp11)]] いれるでOK
77
やったね!
It opens the door to the frontier of C++
こういうコードが書けるようになる
78
Before(C++03)
After(C++0X/11)
※書きなおした後、ふつーに[Build&Load]すればOK ※Rcpp11パッケージなんてのもあるけど、まだ追えてない・・・ ※Windowsの場合、2014年7月現在、Rtoolsのgccが4.6.3なので-std=c++11使えない ※Linux/macならgccの新しい奴入れれば-std=c++11でいけると思う ※gccのヴァージョンとC++0x/C++11の対応などは以下参照 https://gcc.gnu.org/projects/cxx0x.html
79
auto & lambda expression are already engaged!!!
ここまでのコード
80
https://github.com/teramonagi/rOpenWeatherMap/tree/Third
※C++0xの例コードはなし
まとめ • DESCRIPTIONにLinkingTo: Rcpp追記 • NAMESPACEを更新するため、適当な
cppファイルで –@useDynLib rOpenWeatherMap –@importFrom Rcpp evalCpp
を記載 • 後はRcppの方法で倣って書く • WindowsのC++11対応は未完遂
81
3-2:vignetteの作成 with knitr
82
vignetteを作りたい
• vignette≒パッケージ使用例
•かつてはSweave(≒TeX)のみだったものの、 3.0からR markdown(Rmd)による作成もサポート
• ここではR markdownを使った作成法を紹介(出力はHTML)
83
vignetteの例
84 ※ http://cran.r-project.org/web/packages/ggplot2/index.html より
DESCRIPTION
85
VignetteBuilder:knitr の追加
Suggestsにknitr追加
R markdownファイルを追加 • [vignettes]フォルダを作成してその中に保存
86
後で直せる&基本不要っぽいので適当でよさげ
R markdownファイルの例
87 ※細かいR markdownの書き方は「kinitr, markdown」あたりでググれ
ここ以外はふつーの.Rmdと同じ。vignetteIndexEnrtyは一
覧で見た時に表示される名前を入力
結果の確認方法-1
•以下を実行
• [inst/doc]フォルダのHTMLがそれ
88
※以下を参照した。 ※How to get RStudio to automatically compile R Markdown Vignettes? (http://stackoverflow.com/questions/19372260/how-to-get-rstudio-to-automatically-compile-r-markdown-vignettes)
devtools::build_vignettes()
結果の確認方法-2
• 意外とめんどい方法
• 結果の確認手順
1. [Build Source Package]実行
2. 出来たtar.gzを解凍
3. [inst/doc]フォルダのHTMLがそれ
89
結果の確認
• HTMLのvignetteが出来てる
90 ※これがCRANからインストールされる際には自動で出来るんだと思う、多分
まとめ • DESCRIPTIONに –VignetteBuilder:knitr –Suggests:knitr
を追加 • R markdownファイルをvignetteEngineをknitrに指定したうえで、適当に作って、[vignettes]フォルダ下に保存
• 結果はbuild_vignettes関数か、tar.gz作って、その中の[inst/doc]を見る
91
ここまでのコード
92
https://github.com/teramonagi/rOpenWeatherMap/tree/Fourth
3-3:おまけ
93
おまけ的な話を箇条書きで-1
•パッケージに専用データ追加したい
–[data]フォルダ作って、そこにrda
形式でデータを保存しておく。別に他の形式(csv, txtなど)でもいいっぽい。
–パッケージ読込後、data関数でロード可能
94
おまけ的な話を箇条書きで-2
•継続的インテグレーション(CI)したい
–著名な開発者らはtravis使ってる
95 ※ https://travis-ci.org/hadley/dplyrより
おまけ的な話を箇条書きで-2
• travisにSign-In(Githubアカウント) • 画面に従って、適当にボタン押す • .travis.ymlを書いて、Githubにコミット
96 https://github.com/smbache/magrittr/blob/master/.travis.yml
おまけ的な話を箇条書きで-2
• Githubにコミットすると自動テスト • 私もはじめました
97 https://travis-ci.org/teramonagi/RFinanceJ
COMING SOON…?
おまけ的な話を箇条書きで-4
•パッケージ読込時に処理したい
–(慣習的に)zzz.Rというファイルを作成
–.onLoad関数を作って、その中に処理を記述
98
※.onAttach関数でも大体よい。.onLoadとの違いは、.onLoadはNAMESPACEファイルの読込前に実行される一方、.onAttachは.onLoad関数の後、パッケージの環境が見えなくなる前に実行される。
4:参考
99
100
以下、参考資料/BLOG post
2分でパッケージを作ってインストールする
101 http://www.slideshare.net/TokorosawaYoshio/r38
パッケージ作成 ハドリー風
102 http://www.slideshare.net/kaz_yos/r-devtools-roxygen2
英語でいいなら、これ嫁
• [Advanced R] by Hadley Wickham
–http://adv-r.had.co.nz/
• Package Development(Rstudio)
–https://support.rstudio.com/hc/en-us/sections/200130627-package-Development
103
• Writing R Extensions
–http://cran.r-project.org/doc/manuals/R-exts.html
• How R Searches and Finds Stuff
–http://obeautifulcode.com/R/How-R-Searches-And-Finds-Stuff/
104
英語でいいなら、これ嫁
• Writing an R package from scratch
–http://hilaryparker.com/2014/04/29/writing-an-r-package-from-scratch/
105
英語でいいなら、これ嫁
Enjoy!!! 106