整数や実数の数、その四則演算など、計算について説明する。プログラミングでは変数に代入された数値が整数なのか、実数なのか、といったデータ型は気にしておかないといけない。また、さまざまな場面で乱数を使うことがよくある。そのやり方を把握しておこう。
整数や実数(小数点や指数の表示)は、C言語などのプログラミング言語と同じように扱うことができる。記号”#”はコメントを表す。
> #整数
> 4
[1] 4
> -8
[1] -8
> #実数
> 23.456
[1] 23.456
> 4.011e2
[1] 401.1
> 4.011e+20
[1] 4.011e+20
> #円周率pi
> pi
[1] 3.141593
> #標準的な出力より、桁を増やす
> print(pi, digits=10)
[1] 3.141592654
Rでは、C言語のようにintやdoubleなどの数値データの型を気にしなくてもよく、適切な型変換が自動的に行われる。
四則演算は記号”+ - * /”を用いる。計算順序の指定は丸括弧()で行う。記号間の空白は無視されるので、見やすさのために適宜空白を入れるとよい。
> #整数の計算
> 1+2+3+4+5+6
[1] 21
> (2+4)*(3+5)/8
[1] 6
> #実数の計算
> 1.7+7-0.06+8.2/4
[1] 10.69
> #指数表示
> 1.56e10*3.78e-12/0.21e5
[1] 2.808e-06
> pi*6.5/1.8e8
[1] 1.134464e-07
一般的に使われる関数は、C言語などのプログラミング言語とほぼ同じ名称になっている。
> #平方根
> sqrt(2)
[1] 1.414214
> #べき乗
> 8^(1/3)
[1] 2
> #指数関数
> exp(10)
[1] 22026.47
> #自然対数の底e=exp(1)
> exp(1)
[1] 2.718282
> #対数関数
> log(10) #自然対数
[1] 2.302585
> log10(10) #底が10
[1] 1
> log2(10) #底が2
[1] 3.321928
> #三角関数(sin, cos, tan):単位はラジアン
> sin(pi/2)
[1] 1
> tan(45/180*pi)
[1] 1
>
無限大(Inf)や非数(NaN)などの特殊な数が用意されている。
> #無限小
> log(0)
[1] -Inf
> #非常に大きな値として計算
> -1*log(0)
[1] Inf
> #Not a number(数として扱えない)
> sqrt(-1)
[1] NaN
Warning message:
In sqrt(-1) : NaNs produced
>
関数is.finite()、is.infinite()、is.nan()等を使って、計算結果がどのような数であるかを調べる。値が有限か、無限か、非数かを知ることができる。
> #無限大なのか非数なのか確認
> is.finite(1/0)
[1] FALSE
> is.infinite(1/0)
[1] TRUE
> is.nan(1/0)
[1] FALSE
> is.nan(sqrt(-1))
[1] TRUE
Warning message:
In sqrt(-1) : NaNs produced
>
関数runif()やrnorm()は、特定の分布に従う擬似乱数を生成する。ただし、乱数の値は生成毎に異なることに注意する。
> #[-1, 1]上の一様乱数を5個生成
> runif(5, min=-1, max=1)
[1] 0.11138595 0.73214321 -0.64408647 0.04497433 -0.54918132
> #最大値と最小値の指定がなければ、[0, 1]上で生成
> runif(5)
[1] 0.66517535 0.07576430 0.08806506 0.22463570 0.58409008
> #平均3、標準偏差2の正規分布で乱数を5個生成
> rnorm(5, mean=3, sd=2)
[1] 3.2584666 0.7657434 0.3569009 4.8501513 3.6843964
> #平均と標準偏差を指定しなければ、標準正規分布(平均0、分散1)
> rnorm(5)
[1] -0.4350436 0.9765863 -0.2097425 -0.4711655 -0.3730027
>
同じ乱数を生成したければ、関数set.seed()によって乱数のシード(乱数生成の初期化に使われる値)を設定する。同じシード値を与えれば、同じ乱数列を生成する。関数sample()で、ランダムな並べ変えや抜き取りを行うことができる。
> #1から10の整数からランダムに5つの異なる数を抜き出す。
> sample(1:10, 5)
[1] 2 3 10 9 1
> sample(1:10, 5)
[1] 6 8 2 10 5
> set.seed(3)
> sample(1:10, 5)
[1] 2 8 4 3 9
> set.seed(3)
> sample(1:10, 5)
[1] 2 8 4 3 9
> sample(1:10, 5)
[1] 7 2 3 5 4
> #1から10の整数から重複を許して、ランダムに5つを抽出
> sample(1:10, 5, replace=TRUE)
[1] 9 2 8 9 3
> #1から10の整数をランダムに並べ替え
> sample(1:10, 10)
[1] 3 1 2 9 8 4 10 5 6 7
>
Rで操作の対象となるものは、オブジェクトと呼ばれる。このオブジェクトには、スカラ、ベクトル、行列(配列)、リスト、データフレームといったデータ構造がある。変数はこれらのデータ構造を持つオブジェクトを格納し、代入には記号”<-”が用いられる。sin、log、piなど関数名に既に使われている名称は避けよう。混乱する。
スカラとして扱われるオブジェクトには、実数、複素数、文字列、論理値などの型がある。実数は、C言語などで用いる場合とほぼ同じように使用できる。
> #変数xに実数5を代入
> x<-5
> #xの中身を表示
> x # print(x)も可
[1] 5
> #( )で、代入結果を計算と同時に表示
> (y<--4.5)
[1] -4.5
>#変数を使って計算
> x+y
[1] 0.5
>#累乗を計算
> x^10
[1] 9765625
> x^100
[1] 7.888609e+69
> x^1000
[1] Inf #実数として保持できる桁が溢れた
>
文字列の操作は比較的単純である。文字列の結合は関数paste()を用いる。
> #'または"で括られた文字は、1つの文字列
> (y<-"open")
[1] "open"
> z<-"university"
> #関数paste( )で文字列を結合する
> paste(y, z)
[1] "open university"
> #結合するとき空白を入れないように、sepオプションに空文字""指定
> paste(y, z, sep="")
[1] "openuniversity"
> #文字列は、そのまま足せない
> y+z
Error in y + z : non-numeric argument to binary operator
>
論理値は、TRUE(T)とFALSE(F)で表現される。関数as.numeric()は、文字列や論理値を数値に変換する。この例ではTとFを使っているが、TRUEとFALSEを用いた方が安全ではある。
> #論理値(真、偽)を扱う
> F
[1] FALSE
> TRUE
[1] TRUE
> #論理積(&)、論理和(|)、否定(!)による論理演算
> !(T & F) | F
[1] TRUE
> #数値として扱う
> as.numeric(T)
[1] 1
> as.numeric(F)
[1] 0
> #数値として処理
> T+F+T
[1] 2
>
ベクトルは、同じデータ型を持つスカラの集合(配列)である。関数c()を使って生成でき、その要素を参照するには[ ]で要素番号を指定する。
> #関数c()で、同じ型のスカラを並べる
> (x<-c(0,1,2,3,4,5))
[1] 0 1 2 3 4 5
> (y<-c("open","university"))
[1] "open" "university"
> #文字列と数字が混在すると、すべて文字列
> (z<-c("open", 1))
[1] "open" "1"
> #[ ]で番号を指定して、要素を抽出(ベクトルの3番目の要素)
> x[3]
[1] 2
> #複数の要素を取り出すには、番号をベクトルで指定(1と3と5番目)
> x[c(1,3,5)]
[1] 0 2 4
> #実数の系列を等間隔に作るには、関数seq()を使う。
> #0から3まで、0.5刻みの系列
> seq(0, 3, by=0.5)
[1] 0.0 0.5 1.0 1.5 2.0 2.5 3.0
> #0から5まで、長さ(要素の数)6の系列
> seq(0, 5, length=6)
[1] 0 1 2 3 4 5
> #1から10まで、1刻みの系列
> 1:10
[1] 1 2 3 4 5 6 7 8 9 10
> #seq(1,10)と等価
> seq(1:10)
[1] 1 2 3 4 5 6 7 8 9 10
> (x<-1:10)
[1] 1 2 3 4 5 6 7 8 9 10
> #xの3番目から8番目の要素を抽出
> x[3:8]
[1] 3 4 5 6 7 8
>
繰り返しの系列を作るには、関数rep()を使う。
> #1を6回繰り返す。
> rep(1,6)
[1] 1 1 1 1 1 1
> #("a","b","c")を2回繰り返す
> rep(c("a","b","c"),2)
[1] "a" "b" "c" "a" "b" "c"
> #(1,2,3)の各要素を4回繰り返す
> rep(c(1,2,3), each=4)
[1] 1 1 1 1 2 2 2 2 3 3 3 3
ベクトル操作の基本的な関数として、length()はベクトルの要素数を求め、rev()はベクトルを反転させる。
> #0から3までを0.3刻み
> (x<-seq(0, 3, 0.3))
[1] 0.0 0.3 0.6 0.9 1.2 1.5 1.8 2.1 2.4 2.7 3.0
> #ベクトルの長さ(要素の数)
> length(x)
[1] 11
> #もう1つベクトルyを作成して、ベクトルを結合
> (y<-2:6)
[1] 2 3 4 5 6
> (z<-c(x,y))
[1] 0.0 0.3 0.6 0.9 1.2 1.5 1.8 2.1 2.4 2.7 3.0 2.0 3.0 4.0 5.0 6.0
> #ベクトルの反転
> rev(z)
[1] 6.0 5.0 4.0 3.0 2.0 3.0 2.7 2.4 2.1 1.8 1.5 1.2 0.9 0.6 0.3 0.0
>
行列を作る基本的な方法は、関数matrix()を用いてベクトルを並べ変えるものである。
> #ベクトルを行列に変換
> (x<-0:7)
[1] 0 1 2 3 4 5 6 7
> #2行4列の行列に変換(ベクトルの要素の順番に注意)
> (A<-matrix(x, 2, 4))
[,1] [,2] [,3] [,4]
[1,] 0 2 4 6
[2,] 1 3 5 7
> #byrowで、ベクトルの要素の順番を変える
> (B<-matrix(x, 2, 4, byrow=TRUE))
[,1] [,2] [,3] [,4]
[1,] 0 1 2 3
[2,] 4 5 6 7
> #行列の和
> A+B
[,1] [,2] [,3] [,4]
[1,] 0 3 6 9
[2,] 5 8 11 14
行列の転置には、関数t()を用いる。行列の積には、%*%を用いる。単なる”*”だと、行列の成分ごとのかけ算になる。
> #行列の積を計算
> A %*% t(B)
[,1] [,2]
[1,] 28 76
[2,] 34 98
関数cbind()とrbind()を使えば、同じ長さの複数のベクトルを列ベクトルとして横に並べて、あるいは行ベクトルとして縦に並べて結合できる。
> #同じ長さのベクトルの結合
> x<-0:3
> y<-4:7
> #列ベクトルとして結合(column)
> cbind(x,y)
x y
[1,] 0 4
[2,] 1 5
[3,] 2 6
[4,] 3 7
> #行ベクトルとして結合(row)
> rbind(x,y)
[,1] [,2] [,3] [,4]
x 0 1 2 3
y 4 5 6 7
> #対角行列に対して、関数diag()が用意されている。
> #対角行列を生成
> diag(c(0,1,2))
[,1] [,2] [,3]
[1,] 0 0 0
[2,] 0 1 0
[3,] 0 0 2
> #3×3の単位行列を生成
> diag(3)
[,1] [,2] [,3]
[1,] 1 0 0
[2,] 0 1 0
[3,] 0 0 1
> #行列の要素を取り出すには、その要素を指定する。列ベクトルや行ベクトル、あるいは行列のブロックを取り出すこともできる。
> #2行4列の行列を生成
> (x<-matrix(seq(1, 15, by=2), 2, 4))
[,1] [,2] [,3] [,4]
[1,] 1 5 9 13
[2,] 3 7 11 15
> #行列の次元
> dim(x)
[1] 2 4
> #行数
> nrow(x)
[1] 2
> #列数
> ncol(x)
[1] 4
> #2行3列の要素
> x[2,3]
[1] 11
> #2行目の要素
> x[2,]
[1] 3 7 11 15
> #3列目の要素
> x[,3]
[1] 9 11
リストは、異なる構造のデータをまとめて1つのオブジェクトとして扱えるようにする。形式的には、リストはオブジェクトの順序列だが、1つのリストの各要素がそれぞれ異なった型のベクトルであっても構わない。
> #関数list()でリストを生成
> interest<-list(month=c(4, 5, 6), rate=c(1.5, 1.7, 1.8), brand="OpenBank")
> interest
$month
[1] 4 5 6
$rate
[1] 1.5 1.7 1.8
$brand
[1] "OpenBank"
> #monthの要素
> interest$month
[1] 4 5 6
> #rateの2番目の要素
> interest$rate[2]
[1] 1.7
> #interestの3番目の項目
> interest[3]
$brand
[1] "OpenBank"
>
リストの各要素は、それぞれのデータ構造に基づいて操作される。ここでは、項目名の取り扱いについて例示する。
> #リストの各要素の名前はnamesを使って、後から指定できる
> (interest0<-list(c(4, 5, 6), c(1.5, 1.7, 1.8), "OpenBank"))
[[1]]
[1] 4 5 6
[[2]]
[1] 1.5 1.7 1.8
[[3]]
[1] "OpenBank"
> names(interest0)<-c("month", "rate", "brand")
> interest0
$month
[1] 4 5 6
$rate
[1] 1.5 1.7 1.8
$brand
[1] "OpenBank"
> names(interest0)
[1] "month" "rate" "brand"
> # 3番目の項目の名前を変更
> names(interest0)[3]<-"company"
> names(interest0)
[1] "month" "rate" "company"
> #要素の一部を除外するには、NULL(空)を代入する
> interest0$rate<-NULL
> interest0
$month
[1] 4 5 6
$company
[1] "OpenBank"
> #リストの要素は、monthとcompanyだけになっている
データフレームはリストの一種であり、列ベクトルを横に並べたデータ構造を持つ。列ベクトルはすべて同じ長さを持ち、一列ずつデータを作成してデータフレームを作る。行列やリストは、データフレームに変換することができる。ただし、各項目の長さが異なる場合は、長さを揃えるための処理が行われる。リストと同様に、その中にあるベクトルや行列を名前で参照したり、複数のベクトルや行列から横断的にデータを取り出したりすることができる。データフレームは、関数data.frame()を用いて作成する。
> #各項目が同じ長さ(3つ)のベクトルからデータフレームを作る
> (x<-data.frame(month=c(4, 5, 6), rate=c(1.5, 1.7, 1.8), transaction=c(20, 50, 80)))
month rate transaction
1 4 1.5 20
2 5 1.7 50
3 6 1.8 80
> #rateの項目を抽出
> x$rate
[1] 1.5 1.7 1.8
> #2列目を抽出
> x[2]
rate
1 1.5
2 1.7
3 1.8
> #2番目の項目(ベクトル)を抽出
> x[,2]
[1] 1.5 1.7 1.8
> #2行目を抽出
> x[2,]
month rate transaction
2 5 1.7 50
>
リストからデータフレームを作成する。
> #各項目が同じ長さ(3つ)のベクトルからなるリストを作る。
> (interest1<-list(month=c(1, 2, 3), rate=c(1.8, 2.1, 2.6), transaction=c(40, 60, 90)))
$month
[1] 1 2 3
$rate
[1] 1.8 2.1 2.6
$transaction
[1] 40 60 90
> #関数data.frame()を使って変換
> y<-data.frame(interest1)
> #データフレームに変換されている(リストとの違いに注意)
> y
month rate transaction
1 1 1.8 40
2 2 2.1 60
3 3 2.6 90
>
行列からデータフレームを作成する。
> #行列を作成
> (interest2<-matrix(c(1, 2, 3, 1.8, 2.1, 2.6, 40, 60, 90), 3, 3))
[,1] [,2] [,3]
[1,] 1 1.8 40
[2,] 2 2.1 60
[3,] 3 2.6 90
> #関数data.frame()を使って変換
> z<-data.frame(interest2)
> #データフレームの形式に変換されている(行列との違いに注意)
> z
X1 X2 X3
1 1 1.8 40
2 2 2.1 60
3 3 2.6 90
各の行や列の名前はリスト同様に、後から指定できる。
> #データフレームの行名及び列名を変更
> (x<-data.frame(month=c(4, 5, 6), rate=c(1.2, 1.4, 1.8), transaction=c(40, 60, 90)))
month rate transaction
1 4 1.2 40
2 5 1.4 60
3 6 1.8 90
> #行の名前を確認
> rownames(x)
[1] "1" "2" "3"
> #行の名前を変更
> rownames(x)<-c("Apr", "May", "June")
> #列の名前を確認
> colnames(x)
[1] "month" "rate" "transaction"
> #列の名前を変更
> colnames(x)<-c("tsuki", "riritsu", "torihiki")
> #変更後のデータフレームを表示
> x
tsuki riritsu torihiki
Apr 4 1.2 40
May 5 1.4 60
June 6 1.8 90
>
オブジェクトの型と同様に、構造を強制的に変換するための関数が用意されている。as.matrix()、as.data.frame()等が使われる。
> #ベクトルの生成
> (x<-c(1, 2, 3, 4))
[1] 1 2 3 4
> #リストに変換
> as.list(x)
[[1]]
[1] 1
[[2]]
[1] 2
[[3]]
[1] 3
[[4]]
[1] 4
> #行列を生成
> (x<-matrix(x, 2, 2))
[,1] [,2]
[1,] 1 3
[2,] 2 4
> #ベクトルに変換
> as.vector(x)
[1] 1 2 3 4
> #リストに変換
> as.list(x)
[[1]]
[1] 1
[[2]]
[1] 2
[[3]]
[1] 3
[[4]]
[1] 4
> #データフレームに変換
> as.data.frame(x)
V1 V2
1 1 3
2 2 4
> #データフレームの生成
> (x<-data.frame(A=c(11, 12, 13), B=c(21, 22, 23)))
A B
1 11 21
2 12 22
3 13 23
> #行列に変換
> as.matrix(x)
A B
[1,] 11 21
[2,] 12 22
[3,] 13 23
>