github & R package

  • この記事はとても良いです(Japanese only)
  • Rパッケージの良さはインストールが簡単でヘルプ記事が必ずついていること One of R's strong points is that installing packages is easy and every package has its help article.
  • その良さはパッケージ作成の側に回ると苦役になる The strong point turns into a labor when you make a package yourself.
  • Githubからインストール可能であれば、ヘルプとかはなくてもよし、という条件で、devtoolsパッケージのinstall_github()関数によって共有できる。そんな低レベルを最低ラインとした、「なんちゃってRパッケージ」を作るとすると、どうするか… Let's make an unofficial package with which you can share your own functions with others but you don't have to make perfect help articles for them, that should be placed in your github account and can be installed by install_github() function in devtools package.
  • 必要なもの Necessary items
    • Githubアカウント Get your own github account.
    • gitコマンドが打てること Get ready to use git command in your environment.
    • Rのdevtoolsパッケージのインストール Install devtools package inR.
    • コンパイラ関係(WindowsならRtools) Get compilers (e.g Rtools ready in case of Windows environment)
  • 共有・公開にも色々なレベルがある There are various ways to open your functions.
    • 関数構成 Regarding types of your functions:
      • R関数のみ R functions only
      • C,C++,Fortranも使う Includes C, C++, and/or fortran
      • Rcppを使う Include Rcpp-based function
    • ヘルプ記事の親切さ Regarding help articles.
      • ヘルプ記事、一切なし No help articles.
      • ヘルプ記事があって、関数のリストが見られるけれど、関数ごとの情報は不備(関数コード自体を読めば良しとする) List of functions are available but no help article for each function.
      • ヘルプ記事をそれなりにきちんと書く Help articles for pertinent R functions.
      • 完璧なヘルプ記事をつける Perfect help articles.

R-function-only; No helps; github & R package

  • この記事の「なんちゃってRパッケージ」はこちら Here is the github containing files and directories handled in this note.
  • githubアカウントでの作業 Tasks in your github account
    • Githubアカウント(アカウント名がryamada22とする)で新しいrepositoryを作る(ry1という名前で作ったとする) Make a new repository (named "ry1" here) in your github account ("ryamada22" is the account name here).
    • "Initialize this repository with a README"というオプションを選んで作る(と、以下の手順で、進められるから) Check "initialize this repository with a README", that is just for you to follow the steps below: When you get familiar with github, you can do whatever you like.
  • ローカルPCのターミナル・コマンドラインでの作業 Tasks on your local PC's terminal.
    • ローカスPCにこのgithub上のレポジトリと連携したフォルダを作る Make a clone directory with the repository ryamada22/ry1 in github, with the command below.
git clone https://github.com/ryamada22/ry1
    • このローカルPCにできたry1フォルダが、ローカルなRパッケージ関係のファイル・フォルダ置き場となる This is working directory to prepare all files in your local PC.
  • ローカルPCのR上での作業 Tasks in R of your laptop PC.
    • 適当なところにパッケージ"ry1"のファイル・ディレクトリを一括作成する Using the command below, make a directory "ry1" somewhere of your choice, but different from the one you cloned github repository above.
library(devtools)
create("ry1")
    • 出来たファイル・ディレクトリのすべてを、先ほど作ったローカルPCのry1フォルダ(gitコマンドで作ったもの)にコピー・ペーストする Everything in the "ry1" should be copy-and-pasted to the repository clone directory.
    • その中のRディレクトリに自作のR関数を書いたファイルを"xxx.R"と拡張子Rで置く In the directory "R" of working clone, put your R function file, "xxxx.R".
    • ここで、「おまじない」がある。自作R関数をパッケージ"ry1の関数として呼び出せるようにするには、以下のように"#' @export"という行を前につける必要がある。つけないと、存在はするけれど、コマンドを打って呼び出すことができない「隠れた関数」として登録される You have to remember the line "#' @export" that should be placed before every R function in your file. With the line, the function can be called in R environment and without the line, the function exists but can not becalled, i.e., hidden.
    • 以下の例では、myfx1,myfx2,myfx4は「使える関数」として登録されるが、myfx3は「隠れた関数」となる。myfx4関数がmyfx3関数を内部で使っていることがわかる Three out of four functions below, myfx1,myfx2, and myfx4 can be called and myfx3 is hidden. myfx3 can not be called and hidden but it is used inside of myfx4.
#' @export
myfx1 <- function(n){
	runif(n)
}
#' @export
myfx2 <- function(n){
	rnorm(n)
}

myfx3 <- function(){
	sample(1:100,1)
}

#' @export
myfx4 <- function(){
	n <- myfx3()
	rnorm(n)
}
    • この仕組みは「NAMESPACE」という領分のことであり、実際、以下のdocument()という関数は@exportと指定した関数を"NAMESPACE"ファイルに書き出す仕事をしており、その結果、パッケージのインストールにおいて、「使える関数」となる This is related to "NAMESPACE". The function document() in devtools package recognizes @export and put the function's name in NAMESPACE file that enables R to call them.
    • ローカルPCの作業ディレクトリをRのワーキングディレクトリとした上で、以下のコマンドを打つ
document()
  • ローカルPCのターミナル作業に戻る Now back to terminal in your local PC.
    • これで最低限のファイル・ディレクトリ構成ができたので、これをgitでgithubに上げる The minimum requirements as sharable package, you push all to the github repository.
      • すべてのファイル・ディレクトリをすべてそのままgithub登録する、initial loadというコメントを付けて登録する All files and directories are pushed with comment "initial load".
git add . -A
git commit -m "initial load"
git push
  • githubに上がっていることを確認 Check your github repository updated.
  • Rに戻って、githubからインストールする Now come back to R and install the github package as below.
install_github("ryamada22/ry1")
library(ry1)
myfx1(10)
myfx2(10)
myfx3()
myfx4()
    • 実行結果 Result of useage of the package.
> library(ry1)
> myfx1(10)
 [1] 0.91510335 0.10974977 0.13381433 0.93149611 0.17102376 0.26383976
 [7] 0.53205206 0.43370195 0.58730543 0.04650688
> myfx2(10)
 [1] -0.05734637  1.08738546  0.79239426  0.08779522 -2.56388943  0.91326601
 [7]  0.89475244  0.10207312 -0.59848483  1.37912377
> myfx3()
 エラー:  関数 "myfx3" を見つけることができませんでした 
> myfx4()
 [1] -0.008770683 -1.421339626 -0.479789837  0.857434897 -0.480416926
 [6] -0.341444693  1.728423778 -1.239214118  1.159230815  0.632934762
[11]  0.820224667 -0.682431580  2.000072385  0.690161604  0.192848793
[16] -1.531770969  0.643237911 -0.199730936  0.115768698 -2.931729257
[21] -0.552433207 -1.084468456 -0.257777893  0.549276135  0.502923588
[26]  0.608504506 -0.453976499 -1.404513788 -0.230720142 -0.095452420
[31]  0.336500868 -0.097334794  0.581883101 -0.497125120  2.049112673
[36] -0.398490353  1.907391731 -1.355915290  0.166240283  0.093674561
[41] -1.026088339  0.381732975  0.307184955  2.071312884 -1.102166349
[46] -0.718100629  0.986155410 -0.125979386 -0.810872744 -0.266219696
[51]  0.766873007  0.751484719 -0.739978218
> 
    • ヘルプ記事はない(書いていないから)(でも、これだけ簡単なら、書き散らしたR関数が散逸しないだけでもありがたい、ともいえそうです) No help articles at all, because you did not write anything for them.

R-function-only; A bit helps; github & R package

  • この記事の「なんちゃってRパッケージ」はこちら Here is the github containing files and directories handled in this note.
  • ヘルプを開いてもどんな関数があるのかもわからないのでは困るので、少しの手間をとることにする No help article is very inconvenient. Let's make functions' name can be found with minimal efforts.
  • R関数ファイルの冒頭に少し付け加えるとヘルプ記事に関数名が表れて、それをたどることができる。また、使用例も提示できる A few lines at the head of R files, help-index page make you accessible to function names. Examples can be shown.
  • この冒頭の#' で始まる諸行はdevtools, roxygen2パッケージが定めたヘルプ記事作成等のためのルールに則った書き方 The lines starting with "#'" are under the rule of packages roxygen2 and devtools and they are designed to make help articles automatically.
#' Dummy title
#'
#' Dummy description.
#' @examples
#' myfx1(10)
#' myfx2(5)
#' myfx4()

#' @export
myfx1 <- function(n){
	runif(n)
}
#' @export
myfx2 <- function(n){
	rnorm(n)
}

myfx3 <- function(){
	sample(1:100,1)
}

#' @export
myfx4 <- function(){
	n <- myfx3()
	rnorm(n)
}
  • ry1のときと同じようにする Do the same as ry1.
    • githubでry2なるレポジトリを作る Make a new repository "ry2".
    • そのcloneをローカルPCに作る Clone it to your local PC.
git clone https://github.com/ryamada22/ry2
    • ローカルの適当なところで Make files/directories with devtools' create() function.
create("ry2")
    • とした上で、githubとリンクしたry2ディレクトリに、中身をコピーする Copy all created by create() into the directory that is a clone of github repository.
    • さらに上掲のRファイルをRディレクトリに置き、R内で Put the R function file with several lines starting with "#'", then do below.
document()
    • とすれば、今度はmanフォルダ配下にRd拡張子のファイルができるので、これをgitでpushする。 Now document() function makes Rd file that will produce help articles. Push them into the github repository.
git add . -A
git commit -m "initial load"
git push
    • した上で、R内から Now you can install the package with install_github()
install_github("ryamada22/ry2")
    • とする。
help(package="ry2")

    • ヘルプに関数が表れ、以下もできる The help article is a bit more helpful with examples ready.
> help(myfx1)
> example(myfx1)

myfx1> myfx1(10)
 [1] 0.4855833533 0.0508817248 0.0002442701 0.1729956369 0.3587742602
 [6] 0.1240029063 0.9949723762 0.8547038008 0.9492026437 0.4630392240

myfx1> myfx2(5)
[1] -0.10737404 -0.24336732  0.02891265 -1.15511815 -0.37972347

myfx1> myfx4()
 [1]  0.68075399 -0.59733297 -0.88444090 -1.11709863  0.51956156 -2.20189769
 [7]  0.95041650  1.13752507  0.28040709 -2.49045772 -0.44143634  0.08091078
[13] -0.69441347  0.27771177 -0.34069538  0.85882135 -1.35573654  0.59540087
[19] -1.58066811  0.49591176  0.55091563  0.10492812 -0.89752846  0.19653910
[25] -1.45184492 -0.12961395  0.33749149 -1.26467991  0.12114392  0.14557968
[31]  0.60271704  1.76527599 -0.14464007 -0.12915736  0.04522390 -1.95035575
[37]  0.62250816 -0.45526105  0.70670769  0.31067635  0.52310174 -0.32906189
[43] -0.64183443  0.25254319 -0.37447017  1.25046523 -0.62680949 -1.28631025
[49]  0.70304051 -1.12430050 -0.20663646 -1.17374434 -2.35430426  1.58416113
[55]  0.70660643 -0.29303836  1.45214592  0.85660933  1.71813104  0.04238457
[61]  0.42764026  0.04008333 -1.62615541 -2.01381894  1.28770989 -0.71058551

C function; No helps; github & R package

  • この記事の「なんちゃってRパッケージ」はこちら Here is the github containing files and directories handled in this note.
  • Cの関数を取り込むには、C関数をダイナミック・リンク・ライブラリにしつつ、それを呼び出す、という仕組みにする必要がある Let's use C functions in your shareable package. When you incude C functions, they should be converted into dynamic link library and the library should be called from your R function.
  • そのために、さらにちょっと工夫が必要 A bit tasks are necessary for it.
    • 一つの工夫はC関係ファイルの置き場をsrcディレクトリとする One task is to have a directory "src" in the working directory.
    • ダイナミック・リンク・ライブラリを呼び出しますよということを1文書く必要がある The other is to add a line indicating to use the dynamic link library.
  • こちらにある、Cで書かれたreverse処理とそれを呼び出すRの関数を拝借する For our practice, borrow a C file and its wrapper function here.
    • まずはCファイル。RそのものがCを使って作られており、その関係から、2つのヘッダincludeを書くのがルール The C file has header lines that are something related to the fact that R is developed with C.
#include <R.h>
#include <Rdefines.h>

/* Take an int vector and reverse it. */
SEXP reverse(SEXP x)
{
    PROTECT(x = AS_INTEGER(x));
    int n = GET_LENGTH(x);
    if (n <= 0) {
        UNPROTECT(1);
        return R_NilValue;
    }

    SEXP y;
    PROTECT(y = NEW_INTEGER(n));

    const int *px = INTEGER_POINTER(x);
    int *py = INTEGER_POINTER(y) + n - 1;
    for (int i = 0;i < n; ++i)
        *py-- = *px++;

    UNPROTECT(2);

    return y;
}
    • 次いで、Rファイル。もちろん@exportしないと「使える関数」としてNAMESPACEファイルに書き込んでくれないから、それを書く。さらに、今作っているry3というパッケージが作るダイナミック・リンク・ライブラリを使うのですよ、という宣言 @useDynLib ry3を書く(ただし、いくつものC関数を呼び出すR関数があるときは、この宣言は1か所書いておけばよい。 Then R function file. This R function should be "@export" 'ed to be used for NAMESPACE issue. Now write a line indicating that the dynamic link library "ry3" is to be made and it should be called. This line should appear in only one of multiple R function files
#' @useDynLib ry3
#' @export

reverse <- function(x) {
    .Call("reverse", x)
}
  • さて。srcフォルダが必要なのだが、これもdevtoolsで作れる。The src directory can be created by a function in devtools.
    • いつものようにry3フォルダ配下に諸ファイル・フォルダを切り、そのあと、「(Rcppでやるように)C,C++,fortranなどを使いますよ」ということを知らせる関数use_rcpp()を打つとsrcフォルダができる Because packages using Rcpp should have the src directory, devtools has a function named "use_rcpp()" for the generation of src directory and it works for C or fortran.
create("ry3")
use_rcpp()
    • Cファイルはsrcフォルダに置き、.CallするR関数はRフォルダに置く Put your C files (including header files if any) in src directory and your R files in R directory.
  • そのうえで Then do as;
document()
    • そうすると、NAMASPACEファイルに You will find a line below in NAMESPACE file.
useDynLib(ry3)
    • という1行が入り、これが「ダイナミック・リンク・ライブラリを使いますよ」という宣言の役に立つ This tells R that the dynamic link library to be generated should be called.
  • このようにして作るry3配下そっくりを、githubのレポジトリのクローンフォルダに置いて、それをレポジトリにpushすれば出来上がり All under ry3 directory should be copy-and-pasted into the clone-directory and push them into github.
  • 使うときは When you use the package, do below.
> install_github("ryamada22/ry3")
> library(ry3)
> reverse(1:10)
 [1] 10  9  8  7  6  5  4  3  2  1
> reverse
function (x) 
{
    .Call("reverse", x)
}
<environment: namespace:ry3>

Fortran function; No helps; github & R package

  • この記事の「なんちゃってRパッケージ」はこちら Here is the github containing files and directories handled in this note.
  • Fortran関数を組み込んでみる Let's try fortran functions.
  • 基本は同じで、use_rcpp()関数を使ってsrcフォルダを作り、そこにfortran関数を置く。そのfortranサブルーチンを呼び出すR関数を書き、ダイナミック・リンク・ライブラリの手当をする Almost similar to the case of C. make src directory with use_rcpp() and put your fortran functions in it. Write R function that uses the fortran subroutines and take care the dynamic link library issue.
  • こちらにある、C,Fortranを組み込むtoy packageからfortranの簡単関数を拝借する Borrow and modify the simple and easy fortran file and R function here.
      subroutine foo(x, n)

      integer i
      integer n
      double precision x(n)

      do 10 i = 1, n
          x(i) = x(i) ** 2
   10 continue

      end
    • Rの呼び出し関数 R function using the fortran subroutine.
#' @export
#' @useDynLib ry4

foo <- function(x) {
    stopifnot(is.numeric(x))

    out <- .Fortran("foo", x = as.double(x), n = length(x), PACKAGE = "ry4")
    return(out$x)
}
  • 手順は同じ Do the same as C.
    • githubでレポジトリを作り Make a new github repository.
    • そのクローンをデスクトップに作る Clone it on your local PC.
    • 一方、devtoolsパッケージのcreate()関数を使ってパッケージの骨格を作り、さらにuse_rcpp()関数を使ってsrcフォルダを加える Make a skeleton of new package with create() function and add src directory with use_rcpp() function.
    • それを一括してローカルのgitクローンにコピーして、そこにR関数、C関数、Fortran関数を置いて、document()する Copy-and-paste all to the github-clone directory and put R, C, and fortran files in R, src and src directories, respectively.
    • それをgitでpushして git push them to github.
    • install_github()する install_github from the github repository.
> library(ry4)
> foo(30)
[1] 900
> foo(1:10)
 [1]   1   4   9  16  25  36  49  64  81 100
> foo
function (x) 
{
    stopifnot(is.numeric(x))
    out <- .Fortran("foo", x = as.double(x), n = length(x), PACKAGE = "ry4")
    return(out$x)
}
<environment: namespace:ry4>

Rcpp; No helps; github & R package

  • この記事の「なんちゃってRパッケージ」はこちら Here is the github containing files and directories handled in this note.
  • Rcppのよさは、Rcppファイルを作ると、Cpp関数をRから呼び出す関数(ラッパー関数)を書く必要がないこと Rxpp is a package to use Cpp for R and using the package you only have to write Cpp file but don't have to write R-wrapper.
  • C,Fortranと同じ手続きで、以下のファイルを作ること。@exportも忘れないこと Remember @export your Rcpp-based function by adding `export as below. Otherwise almost identical with the cases of C and fortran
  • #' @useDynLib ry5をRファイルのどこかに書くことを忘れないこと Also write the line #' @useDynLib ry5 in one of R files.
  • http://r-pkgs.had.co.nz/src.html:tite=参考記事 (reference)
#include <Rcpp.h>
using namespace Rcpp;
//' @export
// [[Rcpp::export]]
double meanC(NumericVector x) {
  int n = x.size();
  double total = 0;

  for(int i = 0; i < n; ++i) {
    total += x[i];
  }
  return total / n;
}

Helpファイルを充実させる; github & R package

  • ヘルプファイルは、各関数を1関数-1Rファイルとしたうえで、特定の書式に従って書くことによって充実させられる Now you may want to or have to make help files appropriate for semi or full-official package style. Write each R file for each R function one by one with appropriate heading lines.
  • そこらにあるパッケージの作り方、roxygen2の使い方にもよく書いてあるのでそれを参照すること You can find websites on the formats of headers in roxygen2-based style easily.

ほかのパッケージの関数を使う; github & R package

  • この記事の「なんちゃってRパッケージ」はこちら Here is the github containing files and directories handled in this note.
  • 次のようなMCMCpackパッケージのridichlet()関数を使った関数をパッケージ内に使いたいとする You may want to use some R package(s) in your functions, for example MCMCpackage's rdirichlet() as below.
  • そんなときは、hogePackage hagefunctionをインポートする Add a line importing hoge-package hagefunction.
  • hogePackageがインストールされていなければうまく回らないが、インポートされていればOK When your R environment has installed the package already, your own package's function will work fine.
#' @export
#' @importFrom MCMCpack rdirichlet

myfxDirichlet <- function(n,m){
	MCMCpack::rdirichlet(n,rep(1,m))
}