東京R非公式おじさんが教える本当に気持ちいいパッケージ作成法

18,705 views

Published on

Presentation document in TokyoR#42.

Published in: Engineering

東京R非公式おじさんが教える本当に気持ちいいパッケージ作成法

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

×