第20章 Rプログラミング応用
Rによる、より高度な作業のために
- 代表的なオブジェクトのクラス
- オリジナルの関数の作成
- ループや条件分岐
などを学びます。
20.1 オブジェクトのクラス
オブジェクトの種類をクラスと呼びます。
class()
にオブジェクトを入力するとクラスが分かります。
最も使われるのは数値 ()numeric, real) です。
## [1] "numeric"
厳密には数値と整数 (integer) は異なりますが、気にしないといけない局面は少ないと思います。
## [1] "integer"
他には、文字列 (character) や
## [1] "character"
論理値 (logical) などもあります。
## [1] "logical"
論理値は主に条件式が満たされるかどうかを示します。
## [1] TRUE
## [1] FALSE
ちなみに、TRUE
は数値としての1
、FALSE
は0
にもなります。
## [1] 2
## [1] 0
また、因子型 (factor) と呼ばれるクラスもあります。 カテゴリカル変数と言ったほうが分かりやすいかもしれません。
## [1] 1
## Levels: 1
## [1] "factor"
X
の中身は1
ですが、数値ではなくカテゴリーになっているので、数値として操作することはできません。
## Warning in Ops.factor(x, 1): '+' not meaningful for factors
## [1] NA
Rではベクトルには特別なクラスは付与されていません。
ベクトルはc()
に中身を入力して作成します。
## [1] 1 3 5
行列 (matrix) はクラスとして存在します。
## [,1] [,2]
## [1,] 1 5
## [2,] 3 7
## [1] "matrix" "array"
他に、データフレーム (data.frame) やリスト (list) などもあります。
クラスを確認するときは、is.*()
の形をとる関数を使います。
## [1] TRUE
## [1] FALSE
クラスを変更するときは、as.*()
のような関数を使います。
## [1] 1
## Levels: 1
## [1] "1"
- 必ずしも全てのクラスが任意のクラスに変換できるわけではありません(例えば、文字列から数値など)。
20.2 関数の作成
Rで関数を自作する際はfunction(){}
という関数を使います。
()
の中に入力引数を記述します。{}
の中に処理内容を記述し、最後にreturn()
で出力引数を指定します。
例えば、数値ベクトルを入力引数として、平均と標準偏差を出力引数とする関数を作成します。
mean_sd <- function(x) { # 入力引数の名前をxとしておきます。
mean.x <- mean(x) # 平均を計算します。
sd.x <- sd(x) # 標準偏差を計算します。
return(c(mean.x, sd.x)) # 出力引数を指定します。
}
実際に実行してみます。
## [1] -0.01472691 0.96133642
20.3 ループ
ループとは同一の処理を複数回実行することを指します。 例えば、100個の標準正規分布に従う乱数の平均を5回求める処理は次のようになります。
## [1] 0.09851629
## [1] 0.0636278
## [1] -0.1019185
## [1] -0.01609289
## [1] -0.04542928
for
ループとは()
の中のin
のあとのベクトルの第1要素から順番にi
に代入して繰り返しています。
そのことは、次の例から解ると思います。
## [1] "a" "b" "c" "d" "e" "f"
letters
とはアルファベットのベクトルです。
## [1] "a"
## [1] "b"
## [1] "c"
## [1] "d"
## [1] "e"
## [1] "f"
for
ループとは別に、特定の条件が満たされるまで繰り返されるwhile
ループもあります。
ループ処理の結果を格納するには少しテクニックが必要です。
100個の乱数の平均を5回取ったものをx
として保存したいとします。
まず、x
をNULL
オブジェクトとして作成します。
## NULL
NULL
とは空っぽのオブジェクト(0という数値や空白という文字ではない)です。
先程のループ処理の中で、計算した平均をc()
でx
にくっつけていきます。
## [1] 0.01242996 0.00349691 -0.07151655 -0.01892009 -0.17742199
無事、5個の平均値がx
に保存されていることがわかります。
実際にfor
ループの中で何が起こっているかは、次のコードで解ると思います。
## [1] 0.07132597
## [1] 0.07132597 0.01892245
## [1] 0.07132597 0.01892245 -0.16014605
## [1] 0.07132597 0.01892245 -0.16014605 -0.04272138
## [1] 0.071325969 0.018922447 -0.160146050 -0.042721381 -0.003891877
- ループが一周するたびに、前回の
x
に新しい要素が付け加わり、新しいx
として保存されています。
NULL
オブジェクトを使ったループ結果の保存でよくあるミスは、やり直す際にNULL
でリセットするのを忘れることです。
例えば、同じコードをもう一度実行しましょう。
## [1] 0.071325969 0.018922447 -0.160146050 -0.042721381 -0.003891877
## [6] 0.181980210 0.017098258 0.234961971 0.007104972 -0.021349265
x
に10個の平均値が入っています。
このようなミスを避ける方法の一つは、全体を関数として作成することです。
multi_mean <- function() {
x <- NULL
for (i in 1:5) {
x <- c(x, mean(rnorm(100)))
}
return(x)
}
x <- multi_mean()
x
## [1] 0.02361923 0.10858991 0.11928147 -0.05369383 0.19632307
20.4 条件分岐
条件分岐とは、特定の条件の場合に特定の動作を行うようにすることです。
例えば、正の場合positive
、負の場合negative
と出力するコマンドは次のようになります。
## [1] "positive"
## [1] 0.1087327
if(){}
の()
の中に条件式を書き、{}
の中に処理内容を書きます。- それ以外の条件は
else
で示します。
条件式は3つ以上でも構いません。
x <- rnorm(1)
if (x > -0.5) {
print("x is less than -0.5.")
} else if (x >= -0.5 & x <= 0.5) {
print("x is between -0.5 and 0.5.")
} else {
print("x is more than 0.5.ー")
}
## [1] "x is less than -0.5."
## [1] 1.066247
&
は「かつ」を意味します。- 「または」は
|
を使います。 >=
は \(\geq\) を意味します。- 「同じ値である」は
==
を使います(=
ではない点に注意)。
20.5 練習問題
20.5.1 フィボナッチ数列
フィボナッチ数列とは以下の条件を満たす数列です。
\[ \begin{aligned} F_0 &= 0 \\ F_1 &= 1 \\ F_{n} &= F_{n-1} + F_{n-2} \quad n \geq 2 \end{aligned} \]
例えば、
\[ \begin{aligned} F_2 = 1, F_3 = 2, F_4 = 3, F_5 = 5, F_6 = 8,\ldots \end{aligned} \]
となります。
フィボナッチ数列の第\(n\)項を(解析解を使わずに)求める関数を作成してみて下さい。
また、\(F_n \geq m\)となるような\(n\)を求める関数を作成してみて下さい。
20.5.2 モンテカルロ・シミュレーション
モンテカルロ・シミュレーション(モンテカルロ法)とは乱数を用いて近似解を求める手法です。
例えば、円周率\(\pi\)の近似解は以下のように求めることができます。
- 0以上1未満の一様分布から\(n\)個の乱数\(x_i\)と\(n\)個の乱数\(y_i\)を発生させます (\(i = 1,2,\ldots,n\)) 。
- 原点と\((x_i,y_i)\)の距離が1以下である回数を計算し\(n_1\)とします。
- 円周率の近似解として\(\hat{\pi} = 4 \times n_1/n\)を得ます。
モンテカルロ・シミュレーションによる円周率の近似解を求める関数を作成してみて下さい。
また、モンテカルロ・シミュレーションによる円周率の近似解を\(m\)回求めて、その平均値や標準偏差が\(n\)によってどのように変化するか検討してみて下さい。