R風のコーディングスタイル
他の多くの計算機言語と同じく,RにもRらしいコーディングスタイルがある.例えば Googleのスタイルガイド では以下のようなスタイルが推奨されている.以下はその簡訳である.
ファイル名は .R で終わり,意味を持つべきである.オブジェクト名にアンダースコア _ やハイフン - を使わない.変数名は全て小文字で,単語間はドット . で分離する.関数名は動詞にし,先頭が大文字で,ドットを含まない.定数名は関数名に倣うが先頭に k を付ける.例外として,クラスオブジェクト名では,関数(構成子)とクラスは対応する名前を持つべきである(例 lm).
ファイル名: 良 predict_ad_revenue.R 不可 foo.R オブジェクト名: 良 avg.clicks 可 avgClicks 不可 avg_Clicks 関数名: 良 CalculateAvgClicks 不可 calculate_avg_clicks, calculateAvgClicks 定数名: 良 kConstantName (先頭にkを付ける)
一行は半角文字で80文字以下にする.インデントは空白二文字にし,タブや,タブと空白の併用は避ける.もし括弧の中で行替えするなら,折り返した行は括弧の中の最初の文字位置に揃える.二項演算子の前後には空白一文字を置く.但し,関数呼び出しにおける = の前後に空白を置くかどうかは好みである.コンマの前には空白を置かない.コンマの後には必ず空白を置く.
良い例: tab.prior <- table(df[df$days.from.opt < 0, "campaign.id"]) total <- sum(x[, 1]) total <- sum(x[1, ]) 悪い例: tab.prior <- table(df[df$days.from.opt<0, "campaign.id"]) # < の前後に空白を置く tab.prior <- table(df[df$days.from.opt < 0,"campaign.id"]) # コンマの後に空白を置く tab.prior<- table(df[df$days.from.opt < 0, "campaign.id"]) # <- の前に空白を置く tab.prior<-table(df[df$days.from.opt < 0, "campaign.id"]) # <- の前後に空白を置く total <- sum(x[,1]) # コンマの後に空白を置く total <- sum(x[ ,1]) # コンマの前ではなく後に空白を置く
関数呼び出しを除き,右括弧の前には空白を一つ置く.
良い例: if (debug) 悪い例: if(debug)
= や <- 位置での整列のために,余分な空白を置くことは構わない.
plot(x = x.coord, y = data.mat[, MakeColName(metric, ptiles[1], "roiOpt")], ylim = ylim, xlab = "dates", ylab = metric, main = (paste(metric, " for 3 samples ", sep = "")))
括弧や鈎括弧中のコードの周りに空白を置かない.例外として,コンマの後には常に一つの空白を置く.
良い例: if (debug), x[1, ] 悪い例: if ( debug ), x[1,]
左波括弧だけの行は作らない.右波括弧は必ず単独の行とする.単一実行文ブロックに対する波括弧の使用,不使用は統一する.
どちらでも良いが,混在は避ける if (is.null(ylim)) { ylim <- c(0, 0.06) } もしくは if (is.null(ylim)) ylim <- c(0, 0.06)
一つのブロックの最初は必ず新しい行に置く.
悪い例: if (is.null(ylim)) ylim <- c(0, 0.06) if (is.null(ylim)) {ylim <- c(0, 0.06)}
else は波括弧で囲む.
良い例: if (condition) { one or more lines } else { one or more lines } 悪い例: if (condition) { one or more lines } else { one or more lines } 悪い例: if (condition) one line else one line
変数への付値には <- を用い,= を使わない.
良い例: x <- 5 悪い例: x = 5
行の最後にセミコロンを置いたり,一行に複数の実行文を置くためにセミコロンを使わない.セミコロンは無くても不都合はなく,他の Google スタイルガイドラインとの一貫性から使用すべきではない.
コードの構成に下記のような同一の順序を用いれば,お互いのスクリプトを早く容易に読み,理解できる.
著作権のコメント 著者のコメント ファイル内容(プログラムの目的,入力,出力を含む)へのコメント source() や library() 実行文 関数定義 もし適用可能なら(例えば print, plot),実行文
ユニットテスト(コードの正確さや,バグ検証用のテストプログラム)は originalfilename_test.R という名前の別ファイルにすべきである.
コードにはコメントを付けるべきである.コメント行は # と一つの空白で始まるべきである.短いコメントは該当コードの次に,二つの空白,# そしてひとつの空白を置いた後に置いても良い.
hist(df$pct.spent, breaks = "scott", # method for choosing number of buckets main = "Histogram: fraction budget spent by campaignid", xlab = "Fraction of budget spent", ylab = "Frequency (count of campaignids)")
関数定義では,先ず既定値を持たない仮引数,次に既定値を持つ仮引数を並べるべきである.関数定義でも,関数呼び出しでも,一行に複数の引数を置いて良い.改行は付値の間で行うべきである.
良い例: PredictCTR <- function(query, property, num.days, show.plot = TRUE) 悪い例: PredictCTR <- function(query, property, num.days, show.plot = TRUE)
関数は関数定義行の直後にコメントを含むべきである.これは関数の一つの文章による解説,関数仮引数の Args: で始まるリスト(データタイプを含む各々の解説を含む),Returns: で始まる返り値の説明を含むべきである.コメントは,利用者が関数コードを見なくても済む程度に詳しくなければならない.以下は一つの典型例である.
CalculateSampleCovariance <- function(x, y, verbose = TRUE) { # Computes the sample covariance between two vectors. # # Args: # x: One of two vectors whose sample covariance is to be calculated. # y: The other vector. x and y must have the same length, greater than one, # with no missing values. # verbose: If TRUE, prints sample covariance; if not, not. Default is TRUE. # # Returns: # The sample covariance between x and y. n <- length(x) # Error handling if (n <= 1 || n != length(y)) { stop("Arguments x and y have different lengths: ", length(x), " and ", length(y), ".") } if (TRUE %in% is.na(x) || TRUE %in% is.na(y)) { stop(" Arguments x and y must not have missing values.") } covariance <- var(x, y) if (verbose) cat("Covariance = ", round(covariance, 4), ".\n", sep = "") return(covariance) }
コードの改善,拡張に対するコメント(TODO)は,例えば以下のような,コード全体を通して一貫したスタイルを使うべきである.
TODO(ユーザ名): どうすべきかを示す明確な既述
エラー処理は stop() 関数を使うべきである.attach 関数の使用がエラーを引き起こす例が多いので,使うべきでない.
S言語は二つのオブジェクトシステム S3, S4 を持ち,Rでは両者が使える.
参考文献: Thomas Lumley, "Programmer's Niche: A Simple Class, in S3 and S4", R News 4/1, 2004, pp. 33 - 36: http://cran.r-project.org/doc/Rnews/Rnews_2004-1.pdf
S3メソッドはより簡易であり柔軟である.S4メソッドはより形式的で厳密である.S4オブジェクトとメソッドを使うべきはっきりした理由が無い限り,S3オブジェクトとメソッドを使うべきである.S3, S4メソッドを同時に使うべきでない.S4メソッドはS3継承を無視し,逆もまた真である.S4オブジェクトを使う第一の正当化はC++コードで書かれたオブジェクトを使う必要性であろう.S4総称的メソッドを使う第一の正当化は二つの引数に対するメソッド選択適用の必要性であろう.
上で述べたコーディングのルールは,正当な理由がなければ順守すべきである.既存コードの利用や,第三者のコードの変更は例外となる.
最後に述べるべきこととして,常識を持ち,一貫性を重視すべきということがある.コードの編集時には少し時間を取り,周りのコードを眺め,そのスタイルを吟味すべきである.もし他人が if の前後に空白を置いているならば,同じようにすべきである.もし他人がコメントを * からなる枠で囲っているならば,同じようにしよう.スタイルのガイドラインを持つことの要点は,共通のコーディング表現を持つことで,他人が自分の言いたいことに集中できるようにすることにある.ここで述べた全体的なルールは人々がスタイルを共有するためのものである.勿論ローカルなスタイルも大事である.もしファイルに加えたコードが既存のコードと大幅に異なって見えるならば,読者はその不連続性の故に通読が困難になるであろう.これは避けるべきである.
コードの書き方についてはこれぐらいでいいだろう.当然,コード自体のほうがより興味深いのだから.楽しんでもらいたい.