R の関数は他のプログラミング言語同様、命令のかたまり(モジュール)です。 R の関数を使うときにかならずしも値を渡さなくてもよいですし、関数は意味 のある計算結果を返さない場合もあります。呼ばれたときに行われるさまざま な動作(たとえば画面に Hello, world と 表示するような)が主な機能という 関数も多いです。
VBA の Sub プロシージャと Function プロシージャのどちらの役割も R では 「関数」でおこなう、ということです。R では元々用意されている関数だけでなく、自分で関数を書いて使うことがで きます。一連の処理を書き、それに関数としての名前をつけ、後で使えるよう にします。R の関数を定義する、すなわち処理と名前を結びつけて名前で処理 を呼べるようにするには、以下のようにします。
関数名 <- function(もしあれば引数の名前) { 処理の内容 }この書き方は変数に値を代入したときと似ています。 <- の前に名前(前は変 数の、今度は関数の)を書き、 <- のあとにはその名前で呼び出したい内容 (先程は変数の値、今度は関数の処理内容)を書きます。
JavaScript も同じような書き方ができます。これは、関数をオブジェクトとし て扱える言語ということなのですが、ここでは詳細は略します。前述の挨拶プログラムを関数として定義するには プログラムファイルの内容を 以下のように書き換えます(これを hello4.R という名前で名前をつけて保存 しなおしてください)。
hello.goodby <- function() { x <- ('Hello, world\n') # あいさつの文字列を変数 x に代入する。 cat(x) # 変数 x を関数 cat に渡す。 x <- ('good bye, world\n') # 別のあいさつを変数 x に代入する。 cat(x) # ふたたび変数 x を関数 cat に渡す。 }そして source('hello4.R') と入力してプログラムを読み込みます。
source() を入力する前に、先週の授業資料にあった↓を忘れず 実行するようにしてください。この段階 では、R に関数の処理内容と名前を教えただけなので、実行はされません。続 けて hello.goodby() と入力してみましょう。関数が呼び出され挨拶が表示さ れるはずです。R が注目する作業ディレクトリを、このプログラムファイルが置いてある 練習用ディレクトリに変更します。やりかたは、まず「ファイル」メニュー から「ディレクトリの変更」を選択し、「フォルダーの参照」が表示され ますので、「rdata」フォルダを選択すれば完了です。あるいは source('I:/rdata/hello4.R') のようにフルパスで指定してくださ い。来週以降も同様です(!)
次は引数を与える例です。
hello.to.you <- function(to.whom) { cat('Hello,', to.whom, '.\n') # cat に表示させたいものは、いくつも並べて渡せる。 cat('good by,', to.whom ,'.\n') }関数名に使える文字は変数名と同じです。hello4.R に上の内容を書きたして source('hello4.R')で読み込みます。 その上で、例えば以下のように挨拶させ たい人の名前を引数として渡して関数 hello.to.you を呼び出します。 引数と して文字列を与えるときは、 引用符で囲む ことを忘れないように します。引用符がないと変数名とみなされます。
hello.to.you('maechan')なお R は、source 関数を使って読み込んだプログラムファイルが、読み込ん だ後でエディタで編集されたかどうかを知ることは当然ながらできません。で すので、プログラムファイルを編集した後はあらためてsourceで 読み込 み直さ ないと、いつまでも前に読み込んだものが有効になっています。
ちなみに python というプログラミング言語では、インデントでブロックを表 現するという文法になっているので、インデントは必須です。後で、このようなインデントが何重にも入れ子になる例もでてきます。繰り返 しのfor 構文や while 構文、条件判断の if 構文など、複雑な構造のプログラ ムほど、きちんと字下げしてその構造を明示することが重要です。プログラム を読んで処理内容を理解するためだけでなく、バグを探したり修正して再利用 したりするためにも、プログラムが見やすく書かれていることが大切です。最 初は手間かもしれませんが、 { と } で囲まれた中はインデントする習慣をつ けましょう。
関数の名前は、内容が分かる(少なくとも想像可能な)名前にすることと、す でに存在する関数名とダブらないことに注意して決めます。すでに使われてい る名前かどうかを知るには、R の入力画面にその名前を打ち込みます。その時 にカッコは付けてはいけません。カッコをつけると、関数を実行させることに なります。すでに存在する関数の名前を入力すると、その内容(プログラムコー ド)が表示されます。
それぞれは、他の言語とほぼ同様の使い方をします。これらは必要に応じて説 明します。さらに、スカラ型ではない、つまり複数のデータを取り扱うためのデータ型と して、
そもそも 次元とは何か? については稿を改めて説明する予定です。
【ソースコード】
price <- c(108,216,162,97) # price object に vector dataを代入 pname <- c("A", "B", "C", "D") # pname object に vector dataを代入 names(price)<- pname # price のラベルを pnameにする price # price を出力 price^2 # priceの2乗を出力 mean(price) #price vector の要素の平均を出力 round(mean(price),0) # price vector の要素の平均の小数点以下を四捨五入 length(price) # price vector の要素数を出力c() という関数は Combine の意で、複数のデータを引数として、それらを束ね たベクトルを作って返り値とするものです。
【実行結果】
> price <- c(108,216,162,97) # price object に vector dataを代入 > pname <- c("A", "B", "C", "D") # pname object に vector dataを代入 > names(price)<- pname # price のラベルを pnameにする > price # price を出力 A B C D 108 216 162 97 > price^2 # priceの2乗を出力 A B C D 11664 46656 26244 9409 > mean(price) #price vector の要素の平均を出力 [1] 145.75 > round(mean(price),0) # price vector の要素の平均の小数点以下を四捨五入 [1] 146 > length(price) # price vector の要素数を出力 [1] 4
【ソースコード】
price <- matrix(0,2,4) # 要素が 0 の 2行4列の行列を定義する price # 行列 price を表示 pname <- c("A", "B", "C", "D") cityname <- c("Osaka","Tokyo") colnames(price)<- pname # price の列ラベルを pnameにする rownames(price)<- cityname # price の行ラベルを citynameにする price[1,] <- c(105,202,155,91) # 1 行目に Vector を 入力 price[2,] <- c(108,216,162,97) # 2 行目に Vector を 入力 price # 行列 price を表示 dim(price) # price の次元(サイズ)を求める nrow(price) # price の行数を求める ncol(price) # price の列数を求める (price[2,3] <- 156) # 数値を代入してその結果を出力する。()で囲まないと代入だけして無言。
【実行結果】
> price <- matrix(0,2,4) # 要素が 0 の 2行4列の行列を定義する > price # 行列 price を表示 [,1] [,2] [,3] [,4] [1,] 0 0 0 0 [2,] 0 0 0 0 > pname <- c("A", "B", "C", "D") > cityname <- c("Osaka","Tokyo") > colnames(price)<- pname # price のラベルを pnameにする > rownames(price)<- cityname # price のラベルを pnameにする > price[1,] <- c(105,202,155,91) # 1 行目に Vector を 入力 > price[2,] <- c(108,216,162,97) # 2 行目に Vector を 入力 > price # 行列 price を表示 A B C D Osaka 105 202 155 91 Tokyo 108 216 162 97 > dim(price) # price の次元(サイズ)を求める [1] 2 4 > nrow(price) # price の行数を求める [1] 2 > ncol(price) # price の列数を求める [1] 4 > (price[2,3] <- 156) # 数値を代入してその結果を出力する [1] 156最後の入力は、代入式に()がついていることに注意が必要です。こうするこ とで、代入した値を式自体の値として評価させる(コンソール出力する)こと が出来ます。
【ソースコード】
df <- data.frame(cbind(LETTERS[1:4], 1:4)) # cbindは同じ長さのデータを列単位に結合する関数 colnames(df) <- c("Symbol","Number") # 列の名前をつける df # 出力 as.matrix(df) # df を matrix に変換ここで、1:4 で 1,2,3,4 という連続した数を表現できることに注意が必要です。
【実行結果】
> df <- data.frame(cbind(LETTERS[1:4], 1:4)) # cbindは同じ長さのデータを列単位に結合する関数 > colnames(df) <- c("Symbol","Number") # 列の名前をつける > df # 出力 Symbol Number 1 A 1 2 B 2 3 C 3 4 D 4 > as.matrix(df) # df を matrix に変換 Symbol Number [1,] "A" "1" [2,] "B" "2" [3,] "C" "3" [4,] "D" "4"
【ソースコード】
ar <- array(0:19, c(2,5,2)) #2 × 5 × 2 の配列に、0 から 19までの値を入れ 作成する。 ar # 出力
【実行結果】
> ar <- array(0:19, c(2,5,2)) #2 × 5 × 2 の配列に、0 から 19までの値を入れ 作成する。 > ar # 出力 , , 1 [,1] [,2] [,3] [,4] [,5] [1,] 0 2 4 6 8 [2,] 1 3 5 7 9 , , 2 [,1] [,2] [,3] [,4] [,5] [1,] 10 12 14 16 18 [2,] 11 13 15 17 19
【ソースコード】
l <- list(c(0:5), c("A","B"), matrix(0:9,2,5)) # それぞれを要素に持つlistを作成する l # 出力
【実行結果】
> l <- list(c(0:5), c("A","B"), matrix(0:9,2,5)) # それぞれを要素に持つlistを作成する > l # 出力 [[1]] [1] 0 1 2 3 4 5 [[2]] [1] "A" "B" [[3]] [,1] [,2] [,3] [,4] [,5] [1,] 0 2 4 6 8 [2,] 1 3 5 7 9
【ソースコード】
v <- c(108,216,162,97) # vector class(v) # 型 出力 m <- matrix(0,2,4) # matrix class(m) # 型 出力 df <- data.frame(cbind(LETTERS[1:4], 1:4)) # data.frame class(df) # 型 出力 a <- array(0:19, c(2,5,2)) # array class(a) # 型 出力 l <- list(c(0:5), c("A","B"), matrix(0:9,2,5)) # list class(l) # 型 出力 is.vector(v) # v が vector か check is.vector(m) # m が vector か check is.list(v) # v が list か check is.list(l) # l が list か check
【実行結果】
> v <- c(108,216,162,97) # vector > class(v) # 型 出力 [1] "numeric" > m <- matrix(0,2,4) # matrix > class(m) # 型 出力 [1] "matrix" > df <- data.frame(cbind(LETTERS[1:4], 0:3)) # data.frame > class(df) # 型 出力 [1] "data.frame" > a <- array(0:19, c(2,5,2)) # array > class(a) # 型 出力 [1] "array" > l <- list(c(0:5), c("A","B"), matrix(0:9,2,5)) # list > class(l) # 型 出力 [1] "list" > > is.vector(v) # v が vector か check [1] TRUE > is.vector(m) # m が vector か check [1] FALSE > is.list(v) # v が list か check [1] FALSE > is.list(l) # l が list か check [1] TRUE
x <- c(10,20,30,40) x = c(10,20,30,40) c(10,20,30,40) -> x assign("x", c(10,20,30,40))ただし、 <-, -> については記号の間は空白 を入れてはいけない(他の場合は大抵無視されるだけ)ということも注意が必 要です。
実際に次のソースを実行すると、以下の【実行結果】 になります。
【ソースコード】
price1 <- c(10,20,30,40) price1 price2 = c(10,20,30,40) price2 c(10,20,30,40) -> price3 price3 assign("price4", c(10,20,30,40)) price4
【実行結果】
>price1 <- c(10,20,30,40) > price1 [1] 10 20 30 40 > > price2 = c(10,20,30,40) > price2 [1] 10 20 30 40 > > assign("price3", c(10,20,30,40)) > price3 [1] 10 20 30 40 > > c(10,20,30,40) -> price4 > price4 [1] 10 20 30 40