Rの関数のざっとした説明
一見、Cなどの手続き型プログラミング言語のものと同様なRの関数ですが、関数型言語だけに柔軟に扱えます。知っておくと楽ができることもあるので、特徴を把握しておきましょう。
Rの関数は、実行できるデータです。
実際、プリミティブ関数function
(バージョン4.1から\
がシノニムとして用意されました)で作成した後、変数に代入して使います。
function(x) 1 + x + x^2
fnc <-fnc(2)
[1] 7
定義と戻り値については、後で説明します。 コピーしても動きます。
fnc
fnc2 <-fnc2(3)
[1] 13
ファイルに保存も簡単にできます。
saveRDS(fnc, "fnc.Rds")
削除も簡単です。
rm(fnc)
読み込みも簡単です。
readRDS("fnc.Rds") fnc <-
1 属性
クラスも定義され、関数か判別する関数も用意されています。
class(fnc)
[1] "function"
is.function(fnc)
[1] TRUE
定義、コード、定義した環境(名前空間)を取得できます。
args(fnc) # 定義を表示
function (x)
NULL
formals(fnc) # 定義を整理して表示
$x
body(fnc) # コードを表示
1 + x + x^2
environment(fnc) # 定義された環境を表示
<environment: 0x55b984e54410>
環境は変数が保存される領域のことですが、詳しくはRの名前空間とスコーピングを参照してください。
2 定義
Rの関数はfunction(定義){ 本体 }
と言う構造の文で作成し、定義は変数名
か変数名=デフォルト値
か...
をカンマで区切って並べます。デフォルト値には式やコードブロック{ ... }
を入れることもできます。
function(a, b = a + 1) a*b fnc <-
と定義し、
fnc(1)
[1] 2
と実行することもできます。
引数の型やサイズの指定はできないので、必要ならばis.numeric
のような関数を使って、関数の本体で確認や分岐をすることになります。
C言語のprintf
で御馴染みの可変長引数もとることができます。Rの可変引数(…)を参照してください。
3 本体
言わずもながですが、コードブロック({...}
)でくくっても大丈夫です。
function(a, b = a + 1){
fnc <-*b
a }
なお、Rの引数は値渡しなので、引数を変更しても呼び出し元に問題はおきません。また、環境を指定した操作を行わない限り、親環境の変数に代入することもありません。親環境の変数の参照はできます。
4
b <- function(a){
fnc <-# 親環境のrを読んで、引数aに足しているが、親環境のaは不変
a + b
a <- 3 # bに3を代入するが、親環境のbは不変
b <-*b
a
}fnc(1) # 15になる
[1] 15
# 4のまま b
[1] 4
親環境、つまり関数の外側の変数に代入したい場合は、<<-
もしくは->>
を用います。
1
b <- function(a){
fnc <- a
b <<-+ 1
a
}fnc(2)
[1] 3
b
[1] 2
4 戻り値
最後に評価された式の値が、関数の戻り値になります。1
と書いておくだけでも式なので、コードの最後に変数名を書いておくことが多いですが、コード中にreturn
関数の引数で戻り値を明示して関数を抜けることもできます。
戻り値のオブジェクトの種類は、行列でもリストでもデータフレームでも構いません。戻り値はひとつのオブジェクトなので、複数の種類のオブジェクトを戻したい場合は、リストをつくってそこに入れて戻すことになります。
対話しながら操作していると、関数の戻り値が画面表示されるわけですが、return
の代わりにinvisible
を使うと表示を抑制できます。戻り値が膨大な関数では、利用者にやさしい関数定義になります。
function(a, b = a + 1) invisible(a*b)
fnc <-fnc(3)
5 置換関数
属性の設定などで用いる置換関数(e.g. names(x) <- c("1st", "2nd", "3rd")
)の定義では、assign
関数を使います。
assign("d<-", function(x, value){
- value
x
}) 100) (x <-
[1] 100
d(x) <- 1
x
[1] 99
6 演算子
Rは関数型言語なので演算子も関数になり、これもユーザー定義をすることができます。
先頭と末尾の文字が%
の演算子の場合は、以下のように簡単に定義できます。
"%t%" <- function(A, B) A %*% B - B %*% A
matrix(round(runif(4, min=0.5, max=9.5)), 2)) (m1 <-
[,1] [,2]
[1,] 8 2
[2,] 9 1
matrix(round(runif(4, min=0.5, max=9.5)), 2)) (m2 <-
[,1] [,2]
[1,] 2 6
[2,] 5 4
%t% m2 m1
[,1] [,2]
[1,] -44 46
[2,] -53 44
実際の利用ではオブジェクトによって操作を変える必要があるため、S3もしくはS4オブジェクト指向システムに沿った記述にしましょう。詳細はRのオブジェクト指向システム(S3/S4/RC)の説明を参照してください。
なお、先頭と末尾の文字が%
ではない+
や-
といった演算子は、S4クラスの関数として定義されています。