Rの基礎

Rの基礎について学ぶ

今回の学習項目


Rを自分のコンピュータにインストールするための方法は 教科書の1章に紹介があります。ウェブ検索すれば、 「Rの簡単インストール」 のようなサイトもたくさん見つけられるでしょう。 要するに、 Rのオフィシャルサイト からDownload and Install R の項で、Download R for Windows (Windows OSの場合)や Download R for Linux (Linux OSの場合)を選び、それぞれのOSに合わせてイ ンストールしてください (Windowsの場合は ファイルをダウンロードしてから、そのファイルを開き、 あとは指示に従ってマウスクリックすればよい。 LinuxのうちUbuntuなどではソースファイルをダウンロードするよりも、 sudo apt-get install r-base-coreという コマンドでインストールするのが簡単だろう)。

RにもIDE(プログラム開発環境)のようなものがあり、Rコマンダーが人気の高いツールである。Rコマンダーについては Rコマンダーのインストールページを見てください。


Rの基本操作

Windowsで動くRはGUI,つまりマウスでRを選択してクリックすると、Rの処理のためのウィンドゥが開いて、対話形式で処理を行うのが基本である。それに対し、LinuxやWindowsでも Rscriptを使うと、Rで書いたプログラムをコマンドプロンプトなどから実行することができる。

ここでは、対話形式でRを使う場合について解説する。

Rを起動すると、Rのウィンドウが画面いっぱいに開くが、適当に縮小して使うか、 もしくは『編集』メニューから「GUIプリファレンス」を選んで、SDIモードに設定して使うほうが使いやすい(ただし、SDIモードに変えるには、そこでSaveを選んでから、Rを立ち上げなおさないといけない)。

Rの標準的な使い方は、あらかじめRのプログラムを書き、Rを起動し、『ファイル』メニューから「スクリプトを開く」によってそのプログラムファイル (Rではスクリプトという)を開いておいてコピー&ペースト、もしくはスクリプト上でControl-Rを押すことによって、Rの処理プログラムにマウスがある行を渡して処理させることである。ただ、Tera Padのようなエディタからでも、コピー&ペーストによってRの処理プログラムに、プログラムやデータを渡すことは可能であ。いずれにせよ、やりやすい方法を選ぶのがよい。

なお、Rを終了させるには、q()もしくは quit()を入力する。 そこで「作業スペースを保存する」かどうか聞いてくるが、それには「いいえ」を選んで良い。

Rの基本演算、関数、定数

Rはインタプリタとして、ユーザーと対話的に処理を行うのが基本である。 これはつまり、Rのコマンドを打ち込むことがいつも期待され、それが文法的なエラーが なければ、即座に実行され、その結果が得られることを意味する。

まずは基本的な算術演算をおこなってみよう。

課題1-1

Rを起動すると > がウィンドゥに表示される。 これは(入力)プロンプトと呼ばれ、Rがユーザーからの入力待ち状態であることを示している。 それを前提知識として、以下を実行してみよう。ここで、 プロンプトの > は入力しないこと。また『茶色』の文字はユーザーからの入力であることを示している。

> 1+2-3
> 1/2
> 2^5
> (1 + 2 - 3 * 4) / 5 ^ 6 * 7000
[結果の表示における[1]の意味]
[課題1-1の答え]

ほとんどのプログラミング言語と同様に算術演算子が使える。以下にその記号と意味を示しておく。

+		# 足し算(加算)
-		# 引き算(減算)
*		# 掛け算(乗算)
/		# 割り算(除算)
%/%		# 整数としての割り算(整数除算)
%%		# 整数で割った余り(剰余)
^		# 累乗
**		# 累乗

演習の結果からわかるように、Rでは実数計算が基本であるため、整数だけの演算であっても、計算は原則として実数として計算される (つまり、例えば2/3のように整数同士の割り算においても結果は実数となる)。

数の大小など「比較」演算子も用意されている。この演算の結果は真理値であり、 TRUEFALSEという値(論理定数)が値となる。これは主に条件文で使われるが、後でみるように、ベクトルの特定の要素を取り出すのにも使われる。なお、 # は、その記号以降、改行までの文は「コメント」として扱われることを表す。

> 5 == 5		# 等号
[1] TRUE
> 5 != 5		# 等号否定
[1] FALSE
> 5 >= 2		# 不等号(以上)、等号を含まない場合は > 
[1] TRUE
> 5 <= 2		# 不等号(以下)、等号を含まない場合は <
[1] FALSE
注意: Rでは大文字と小文字を厳密に区別する。だから、例えばTRUEをtrueと書いたり、 FALSEをfalseと書いてはいけない。

真理値の間の演算、つまり論理演算について紹介する。

> ! (5 == 5)	# 否定
[1] FALSE
> ! (5 != 5)		
[1] TRUE
> (5 >= 2) && (5 <= 2)	# 論理積
[1] FALSE
> (5 >= 2) || (5 <= 2)		# 論理和
[1] TRUE

Rはまた組み込みの関数が数多く用意されている。関数を使うには

sqrt(10)
のように「関数名」の次に引数を括弧でくくって使う。

課題1-2

以下を実行して、値を確かめよ。
>  exp(1.0)
>  cos(1/2)
>  sqrt(1*2/3)
>  log2(2^5)
>  round((1 + 2 - 3 * 4) / 5 ^ 6 * 7000)
[課題1-2の答え]

いろいろな数学関数が使える。以下によく使う関数名と意味を示しておく。

sin		# 三角関数のsin
cos		# 三角関数のcos
tan		# 三角関数のtan
sinh		# 双曲線関数sinh(x) = (e^x-e^(-x))/2
cosh		# 双曲線関数cosh(x) = (e^x+e^(-x))/2
tanh		# 双曲線関数tannh(x) = sinh(x)/cosh(x)
asin		# sinの逆関数 arcsin
acos		# cosの逆関数 arccos
atan		# tanの逆関数 arctan
log		# (自然)対数、底はe
log10		# 常用対数、底は10
log2		# 底を2とする対数
exp		# 指数関数 exp(x)=e^x
sqrt		# 平方根
round		# 小数点を四捨五入
floor		# 小数点以下切り下げ
ceiling		# 小数点以下切り上げ
trunc		# 整数部分
sign		# 符号(正なら1、負なら-1)
abs		# 絶対値
引数が正ならば truncとfloorは結果が一致し、負ならばtruncとceilingは結果が一致する(その理由は?)。

課題1-3

  1. 100**(1/2) と 100**1/2 はそれぞれどのような答えを返すだろうか。予想してからRで実行し、結果を確かめよ。もしも予想と違った場合は、その理由を考えよ。
  2. 2の立方根(3乗根)をRで求めよ。どの関数を使ったら良いだろうか? (答えはひと通りとは限らない)
  3. 123/0.0 はどのような答えを返すだろうか、。予想してからRで実行し、結果を確かめよ。もしも予想と違った場合は、その理由を考えよ。
  4. 0/0.0 はどのような答えを返すだろうか、。予想してからRで実行し、結果を確かめよ。もしも予想と違った場合は、その理由を考えよ。
  5. -123/0.0 はどのような答えを返すだろうか、。予想してからRで実行し、結果を確かめよ。もしも予想と違った場合は、その理由を考えよ。
[課題1-3の答え]

Rでは次のような定数が用意されている。NAは普通のプログラミング言語にはないものであるが、これは統計のための定数である。

pi		# 円周率、3.141593
Inf		# 無限大
NULL		# 空値
NaN		# Not a Number --- 数ではないモノ
NA		# Not Available --- 欠損値
TRUE		# 真理値としての「真」
T		# TRUEと同じ
FALSE		# 真理値としての「偽」
F		# FALSEと同じ


代入

Rにおいて、変数に値を記憶するための方法『代入』(Rでは『付置』と呼ぶ)について述べる。

どんなプログラミング言語でも計算した結果を記憶するための変数があり、 そして変数に計算結果を記憶させる『代入』が用意されている。 Rでも代入があるが、次の特徴を持つ:

課題1-4

  1. 変数xに3.0を代入した後、sin(x)^2+cos(x)^2 の値を計算せよ。
  2. 以下を実行すると、変数aとbにはそれぞれどのような値が入っているか?
    a <- b <- 10
  3. 次の名前のうち、変数名として使えるものと使えないものにわけよ。
     teST   0test   te-st  te.st  te,st test_01 true  T  te..st  te?st   te$st
    
[課題1-4の答え]

ベクトル---複数の値をまとめたもの

Rは複数の値をひとまとめに処理するのが得意な言語である。「複数の値をまとめた」ものの基本をベクトルという(後でこの定義は修正するが、今はこの理解でいてほしい)。

ベクトルの作成

ベクトルは、関数cを用いて作られる。次は、1, 3, 5という3つの数をまとめたベクトルを作って変数xに代入し、3, 4, 5という3つの数をまとめたベクトルを作って変数y に代入する例である。

x <- c(1, 3, 5)      	# 1, 3, 5からなるベクトル
y <- c(3, 4, 5)      	# 3, 4, 5からなるベクトル

今の例ではxの要素は初項が1、公差が2の等差数列であり、yの要素は初項が3、公差が1の等差数列であった。このような要素が等差数列となっているベクトルを、c関数を使うのではなく、より簡単に作るための記法や関数が用意されている。

課題2-1

  1. 次の例を実行して、ベクトルを作る関数seqの引数の意味を説明せよ。
    x1 <- seq(1,5,2)
    y1 <- seq(3,5)
    v1 <- seq(5,1)
    w1 <- seq(5,1,-2)
    
  2. 次の例を実行して、ベクトルを作る記法 数1:数2 により、どのようなベクトルが作られるか、説明せよ。
    y2 <- 3:5
    v2 <- 5:1
    
  3. 次の例を実行して、ベクトルを作る関数「repの引数の意味を説明せよ。
    z1 <- rep(1:3,5)
    z2 <- rep(5:1,3)
    
[課題2-1の答え]

ベクトルの演算

Rの面白い(初心者のうちなかなか慣れない)ところは、本来は一個の数に対する演算や関数がベクトルに対しても使える、というところである。

まず四則演算からみていこう。xyの値を次のように定めておく。

  x <- c(1, 3, 5)      	# 1, 3, 5からなるベク/ル
  y <- c(3, 4, 5)      	# 3, 4, 5からなるベクトル
これらを四則演算してみた結果は以下のようになる:
> x + y		# c(1,3,5)+c(3,4,5)
[1]  4  7 10		# c(1+3, 3+4, 5+5)
> x - y		# c(1,3,5)-c(3,4,5)
[1] -2 -1  0		# c(1-3, 3-4, 5-5)
> x * y		# c(1,3,5)*c(3,4,5)
[1]  3 12 25		# c(1*3, 3*4, 5*5)
> x / y		# c(1,3,5)/c(3,4,5)
[1] 0.3333333 0.7500000 1.0000000	# c(1/3, 3/4, 5/5)
つまり、ベクトル同士の四則演算が、ベクトルの要素ごとの演算とみなされるのである。

次にベクトル一個に対して数を四則演算させてみよう。その結果は以下のようになる。

> x + 10		# c(1,3,5)+10
[1]  11 13 15			# c(1+10, 3+10, 5+10)
> x - 10		# c(1,3,5)-10
[1] -9 -7 -5			# c(1-10, 3-10, 5-10)
> x * 10		# c(1,3,5)*10
[1]  10 30 50			# c(1*10, 3*10, 5*10)
> x / 10		# c(1,3,5)/10
[1] 0.1 0.3 0.5			# c(1/10, 3/10, 5/10)
つまり、ベクトルに対しスカラーを四則演算すると、ベクトルの要素ごとにスカラーが四則演算されるのである。

同じ理屈は、関数に対しても成り立つ。sqrtlogのような関数は一個の数に対して適用されるものである。しかしRではこれもベクトルに適用できる。

> log(x)		# log( c(1,3,5) )
[1]  0.000000 1.098612 1.609438		# c(log(1), log(3), log(5))
> sqrt(x)		# sqrt( c(1,3,5) )
[1]  1.000000 1.732051 2.236068		# c(sqrt(1), sqrt(3), sqrt(5))

logsqrtが本来は一個の数を引数に取るのに対し、 平均値や最大値、最小値を求める関数はベクトルのような複数の値に対し適用される関数である。そしてRではそのようなベクトルを引数にとる関数がたくさん用意されている。

そのいくつかを紹介する

 length		# ベクトルの要素数を求める
 max		# 最大値を求める
 min		# 最小値を求める
 mean		# 平均値を求める
 range		# 値の範囲を求める
 rev		# 要素を逆順にする
 sd			# 標準偏差を求める
 sort		# 要素を整列(ソート)する
 sum		# 要素の和を求める
 var		# 不偏分散を求める

課題2-2

 x <- c(1, 6, 8, -4, 2)      	# 1, 6, 8, -4, 2からなるベクトル
として、ベクトルの演算にあげられている例を実行し、値を求めよ。 その結果によって関数の意味を確認せよ。

[課題2-2の答え]

ベクトルの要素

ベクトルの中のそれぞれの数値を『要素』と呼ぶ。 ベクトルの特定の要素だけを取り出す、もしくは特定の要素を除外したベクトルを求める方法などについて述べる。プログラミング言語Cと異なり、ベクトルの要素の番号は0ではなく1から始まる。

ベクトルの特定の要素を参照する(値を取り出す)には要素の番号を角括弧([ ])の中に指定する。また要素の番号としてベクトルを指定することで、複数個の要素をベクトルとして取り出すことができる。さらに、最後の例のように、[ ]の中に条件式を書くことで、その条件を満たす要素だけからなるベクトルを返すこともできる。

> x <- c(1, 3, 5, -4, 2)    	# 1, 3, 5, -4, 2からなるベクトル
> x[1]			# 1が先頭の要素の番号
[1] 1
> x[length(x)]		# length(x)=5 はxの最後の要素の番号
[1] 2
> x[100]		# 100番目の要素は存在しない
[1] NA
> x[2:4]		# 2番目から4番目までの要素
[1]  3  5 -4
> x[c(3,1,5)]		# 3番目、1番目、5番目の要素を指定
[1] 5 1 2
> x[-c(3,1,5)]		# 番号をマイナスにすると...
[1]  3 -4			# その番号を「除く」要素からなるベクトル
> x[x < 3]		# x< 3という条件を満たす要素を取り出す
[1]  1 -4  2

課題2-3

z <- c(30, 33, 29, 38, 49, 9, 42, 29, 7, 41, 24, 46, 39, 7, 27, 30, 16, 40, 37, 2) 
として、(1) zの要素の中で30以下のものからなるベクトルを返す式、(2)zの要素で30より大きな要素の平均値を求める式、(3) zの要素を小さい順番から並べたときの先頭から5番目までの要素を返す式、(4) zの要素で奇数だけからなるベクトルを返す式、を書け。

[課題2-3の答え]

ベクトルの特定の要素を別な要素で置き換えることができる。それには、ベクトルの特定要素を取り出す式を書き、それに別な要素を「代入」する、という式を書けばよい。 (以下では;を使っているが、これは複数の文を一行で書くための記法である)

> x <- c(1, 3, 5, -4, 2)    	# 1, 3, 5, -4, 2からなるベクトル
> x[1] <- 10 ; x			# x[1]に10を代入
[1] 10  6  8 -4  2				# x[1]が10で置き換わった
> x[10] <- 10 ; x			# 10番目の要素は存在しないが...
 [1] 10  3  5 -4  2 NA NA NA NA 10		# x[10]に10を代入し、存在しない要素にはNAが代入される
> x[6:9] <- 0 ; x			# 6番目から9番目までの要素に0を代入
 [1] 10  3  5 -4  2  0  0  0  0 10		# 6番目から9番目までの要素が0になった
> x[c(3,1,5)] <- c(20,30,40) ; x	# 3,1,5番目の要素に20, 30, 40を代入
 [1] 30  3 20 -4 40  0  0  0  0 10		# 3,1,5番目の要素がそれぞれ20, 30, 40になった
> x[x < 3] <- 50 ; x			# x< 3という条件を満たす要素に50を代入
 [1] 30  3 20 50 40 50 50 50 50 10		# x< 3という条件を満たす要素が50になった

関数の作り方

ここでは関数の定義を中心に説明する。

関数とは、与えられた入力を元に何らかの計算をして出力を返すモノである。 Rはこの定義に従い、関数定義の基本形を次のように定めている:

関数名 <- function(仮引数1, 仮引数2, ...) { 関数本体 }
見てわかるように、「関数名」の値として関数の定義が設定される。 「仮引数」というのが入力を記憶するための変数であり、「関数本体」で計算が行われる。 関数本体の中でreturn文が実行されれば、計算を終了し、returnの引数が関数全体の出力となる。そうでなければ関数本体の最後の文の値が返される。

次は関数定義の例であり、ベクトルを入力として、その要素の2乗の和を返すものである。

square.sum <- function(x) {
		y <- sum(x*x)
		return(y)
	}
[上記の関数のより簡略化した版]

ここでxyは関数square.sumで使われている「局所変数」であり、 その中でしか値は有効ではない。また、仮に次のように関数の外で使われていても、無関係とみなされることに留意しよう。

> x <- 3;  y <- 5		# ;を使うと複数の文を1行で書ける
> square.sum(c(1,2,3)) 		# square.sumを呼び出す
[1] 14			# square.sum中のyの値
> print(y)			# yの値は元のまま
[1] 5

課題2-4

square.sumの定義を参考にして、ベクトルを入力とし、 「その平均値と各要素の差」の二乗の和を返す関数ex2.4を書け。言い換えれば、 入力ベクトルをc(x1, x2, ..., xn)とし、その平均値をmとすると、 (x1-m)^2 + (x2-m)^2 + ... + (xn-m)^2を返す関数を書く。

[課題2-4の答え]

参考

Rの中で関数や変数の値を「編集」(修正や追加、一部を削除すること)することができる(ただし、何らかの値が入っている変数でないとできない)。例えば、関数ex2.4の定義を編集するには、
ex2.4 <- edit(ex2.4)
とやればよい。別なウィンドウが開いて、ex2.4の値、つまり関数を編集することができる。

このページで出てきたRの関数や記号


演習問題

注意: 講義時間中に解いてレポートとして提出する。答だけではなく、 用いたRの関数なども示すこと(ちょうどこの解説におけるプログラムの実行例の表示のように)。また適宜、解説をつけること。 時間内に解けない場合は、次の週の月曜日(1日の猶予あり)までに追加レポートとして提出すること。

演習問題1-1

等しい次元(つまり要素数が同じ個数)のベクトルを2つ引数に取り、 その内積を返す関数dotを作れ。その実行例は以下である: [ベクトルの内積について]

> dot( c(1,2,3), c(-1,1,-1) )
[1] -2
> dot( c(1,2,3), c(1,1,-1) )
[1] 0
次に、あなたの学籍番号の下二桁の数 N により、 関数set.seedを用いて、乱数の初期値を設定する。 次に、乱数発生関数runifと関数rnormにより、 変数xとyに「10個の要素をもつベクトル」を値として与える。 そして、今作ったdot関数を用いて、xとyの内積を求めよ。 以下は、学籍番号がT214099の人の場合の実行例である (この人ではN=99となる)。 [この演習で使われている関数について]

> N <- 99
> set.seed(N)
> x <- runif(10,1,20)
> y <- rnorm(10,-3,3)

演習問題1-2

ベクトルの長さを返す関数 len を作れ。 ここでsquare.sumを用いても良い。 また、演習問題1-1で用いた変数xとyそれぞれのベクトルの長さを答えよ。
なおlenの実行例は以下である:
> len( c(1,2,3) )
[1] 3.741657
> len( c(1,1,-1) )
[1] 1.732051

演習問題1-3

2つのベクトルを引数とし、その間の角のcos値を返す関数cosThetaを作れ。 また、演習問題1-1で用いた変数xとyの間の角のcos値を求めよ。
なおcosThetaの実行例は以下である:
> cosTheta( c(1,2,3), c(1,-1,1) )
[1] 0.3086067

演習問題1-4

(1) 演習問題1-1で用いた変数xとy、それぞれの平均、不偏分散、標準偏差を求めよ。
(2) 次にそれぞれの要素に100を足したベクトルを作り、それぞれの平均、不偏分散、標準偏差を求めよ。
(3) また、それぞれの要素に100を掛けたベクトルを作り、それぞれの平均、不偏分散、標準偏差を求めよ。
(4) そして、平均と標準偏差について、元のベクトル、それに100を足したもの、100を掛けたものとを比較し、どのような関係があるかを述べよ。
[ベクトルから、各要素にある数を足したベクトルや、ある数をかけたベクトルを簡単に作る方法]


                     トップページに戻る                    次の解説を見る