R01:ベクトル周辺

(1)変数と代入

コメントアウト

「#」以下の文はコメントアウトとして扱われます。
文を実行した後に補足的にコメントすることも可能です。

# コメントアウトはシャープを文頭につけます。
print("hello") #helloを出力

代入

変数aに1を代入する場合の記法。
イコールも矢印もどちらも使えます。

a = 1
a <- 1

Rでは矢印が一般的ですが、この授業ではイコール記法を採用します。

文の実行

実行する行を選択し、「⌘RETURN」(MACの場合)でコードを実行すると、
コンソールに以下のように実行結果が表示されます。

> a
[1] 1

変数の書式(ピリオド・大文字と小文字)

ピリオドを変数の表記に使うことも可能です。
(ただし先頭は不可です)

A.a = 0.4; A.b = 0.8
A.a; A.b #セミコロンを使うと一行に複数の文を並べることができます。
> A.a; A.b
[1] 0.4
[1] 0.8
大文字と小文字は区別されます。

name=1; Name=2
name+1 
> name+1
[1] 2

(2)型

代表的な型

Rのデータ型として代表的なものとして、整数型(integer)・倍精度浮動小数点数(double)・論理値(logical)・文字列型(character)を挙げておきます。数字は整数・小数に関わらず、デフォルトでdouble型と扱われます。整数型として扱いたい場合、数字の後ろに明示的に”L”をつけてください。

a = 1 #整数はデフォルトではdouble型として扱われます
b = 0.2 #double型
c = TRUE #logical型(T、F表記も可能)
d = 1L #整数型(integer型)として扱いたい時はLをつける
e = "Hello" #character型

型の参照・変換

データ型はtypeofで調べます。

#上につづき
typeof(a);typeof(b);typeof(c);typeof(d);typeof(e)
[1] “double”
[1] “double”
[1] “logical”
[1] “integer”
[1] “character”
型変換にはas.xxxを使う(xxxには変換したい型の名前)。

a = 1 #この時点ではdouble型 
a1 = as.integer(a) #double型からinteger型に変換
a2 = as.double(a1)
typeof(a1)
typeof(a2)
> typeof(a1)
[1] “integer”
> typeof(a2)
[1] “double”

numericはintegerとdoubleを合わせた型(mode関数で確認可能)

a = 1L; b = 1;
typeof(a);typeof(b)
mode(a);mode(b)
> typeof(a);typeof(b)
[1] “integer”
[1] “double”
> mode(a);mode(b)
[1] “numeric”
[1] “numeric”





(3)ベクトルの生成

コンビネーション

c(n1,n2,n3)でベクトルを生成します。cはcombineに由来します。

a = c(1,2,3)
a = c(T,TRUE,F)
a = c("T","T","F") #文字列の配列
[1] 1 2 3
[1] TRUE TRUE FALSE
[1] “T” “T” “F”

ベクトルの要素は、全て同一の型である必要があります。
異なる型を入れた場合、適当な型に型変換されることに注意してください。

以下の場合、Tと102は強制的に文字列型(character)に型変換されます。

a=c(T,102,"hello");
> typeof(a)
[1] “character”
>a[1];a[2];a[3]
[1] “TRUE”
[1] “102”
[1] “hello”
単なる数値も要素1のベクトルです。つまり、単一の値が代入された変数の値は、変数[1]という形でも取り出すことができます。is.vectorによってフォーマットがベクトルがそれ以外(例えばリスト)かがわかります。

a=2;
> a[1]
[1] 2
> is.vector(a)
[1] TRUE

a:bによる数列の生成

c(a:b)で一次元配列ベクトル(a,a+1,…,b)を作成

a = c(101:105)
a = c(9:1); # b<aのとき(a,a-1, .. b)
#[1] 101 102 103 104 105
#[1] 9 8 7 6 5 4 3 2 1
a = c(-3:9999333)
length(a) #ベクトルの長さはlength関数で取得可能
#[1] 9999337
c(a,b)の引数が非整数の場合は、初項a、公差1で、b以下のものを集めたベクトルを返す。

a = c(2.3:4)
[1] 2.3 3.3
「:記法」の場合, cは省略可能です。

a = 101:105
a = 9:1 
a = 2.3:4
#[1] 101 102 103 104 105
#[1] 9 8 7 6 5 4 3 2 1
#[1] 2.3 3.3

seq関数:分割

seq関数を使うと、第1引数と第2引数の間を分割するベクトルを生成します。

a = seq(1,10,length=5) #1~10を5分割
a = seq(1,10,by=2) #1から2ずつ増やして10を越える手前まで
#[1] 1.00 3.25 5.50 7.75 10.00
#[1] 1 3 5 7 9

rep関数:繰り返し

rep関数は、第一引数のベクトルを、規定回数繰り返します。

a = rep(1:3,times=3) #c(1,2,3)を3回
a = rep(1:3,length=5) #(1,2,3)を要素数5となるまで繰り返す
#[1] 1 2 3 1 2 3 1 2 3
#[1] 1 2 3 1 2

sample関数:無作為抽出

特定の範囲の中からランダムに数列を生成する場合、無作為サンプリング関数(sample)を使います。第一引数が、サンプリング対象となるベクトル、第二引数が抽出する数となります。以下は、1から6の数字まで、ランダムに1つの数字を出力する例です。

a1 = sample(1:6,1) 
a2 = sample(1:6,1) 
b1 = sample(c(2,4,6,8,10),1)
b2 = sample(c(2,4,6,8,10),1)
> a1;a2
[1] 2
[1] 5
> b1;b2
[1] 10
[1] 8

複数の数を抽出する場合、デフォルトでは、「くじ引き」方式(一度使われた数字は使われない)が採用されます。これは、デフォルトでは、replace引数がFALSEに設定されているためです。replace引数をTRUEとすることで、「サイコロ」方式(一度使われた数字を除外せずにサンプリング)となります。

a = sample(1:6,6) #1~6から無作為サンプルを6回(重複なし)
b = sample(1:6,7) #エラー(母数よりサンプル数が多い)
c = sample(1:6,7,replace = TRUE) #replaceをTRUEにセットすると重複ありモードへ
> a;c
[1] 5 2 3 4 6 1
[1] 2 6 4 3 4 4 5

ベクトル変数の宣言(的な)

vector(型名,n)で、サイズnの特定の型のベクトルを生成します。このとき、初期値となる要素は、型によって異なります。
サイズを指定しない場合、宣言だけされた状態で中身は空です。

a = vector("integer") #integer型の空のベクトルを生成(中身は空)
a = vector("logical")
> a; b;
integer(0)
logical(0)
第二引数でサイズを指定すると、デフォルト値がサイズ分だけ代入されます。

a = vector("integer",10) #引数2はベクトルの長さ(初期値は0)
b = vector("logical",10) #logical型の場合、初期値はFALSE
a; b;
> a; b;
[1] 0 0 0 0 0 0 0 0 0 0
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

ベクトルの結合

ベクトルを結合する場合、単にc関数の中に、複数のベクトルを並置します。

a = 101:105; a = c(a,201,202) #2つの要素を追加
b = (a,301:303) #ベクトルaを再帰的にベクトルbの最初の要素に指定
> a; b;
[1] 101 102 103 104 105 201 202
[1] 101 102 103 104 105 201 202 301 302 303
a = c(rep(T,length=20),rep(F,length=10)) #Tを20、Fを10、順に並べたベクトル
b = c(101:105,301:305)
> a; b;
[1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[14] TRUE TRUE TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
[27] FALSE FALSE FALSE FALSE
[1] 101 102 103 104 105 301 302 303 304 305

append関数を使って結合する方法もあります。

a = c(101:105)
b = c(301:305)
c1 = append(a,b) #aとbを結合
c2 = append(a,b,after=2) #3番目の要素から挿入
> c1;c2
[1] 101 102 103 104 105 301 302 303 304 305
[1] 101 102 301 302 303 304 305 103 104 105





(番外編)関数の仕様を調べる。

先ほど、紹介したsample関数は、第1引数に母集団のベクトル、第2引数にサンプル数をとり、logical型のreplace属性を持ち、replace属性のTRUE/FALSEによって、「サイコロ」方式か「くじ引き」方式を決めることができる(デフォルトは、FALSEで「くじ引き」方式)、という仕様を持っていました。これらの仕様は、どのように調べることができるでしょうか。

特定の関数の仕様を調べるには、args関数の引数に、関数名を適用します。以下は、sample関数を調べる例です。

args(sample)
> args(sample)
function (x, size, replace = FALSE, prob = NULL)

上記のx, size,replace,probは、それぞれ、sample関数の引数名です。実は、Rの関数の全ての引数には名前があります。名前が省略されている時、1番目の引数は「x」、2番目の引数は「size」、3番目の引数は「replace」、4番目の引数は「prob」として解釈されます。また「replace」のデフォルト値はFALSE、「prob」のデフォルト値はNULLである一方、「x」と「size」にはデフォルト値がありません(sizeは、実際にはxのベクトルの要素数がデフォルト値となるようです)。引数名が指定されさえすれば、どの位置で引数を与えても問題ありませんが、引数名が省略されている場合、上記の対応に従って引数の意味は解釈されます。

なお、それぞれの引数が何を意味するのかは、関数の前に?をつけて実行してください。

?sample

(RStudioの場合)Help Viewに以下の様な具合で表示されます。

Arguments
[x] either a vector of one or more elements from which to choose, or a positive integer. See ‘Details.’
[size] a non-negative integer giving the number of items to choose.
[replace] should sampling be with replacement?
[prob] a vector of probability weights for obtaining the elements of the vector being sampled.

以上より、以下は全て同じことを意味しています(2、3、4から3つの数字をサイコロ方式でランダム抽出)。

sample(2:4,replace=T)
sample(2:4,3,TRUE)
sample(replace=T,x=2:4,size=3)
sample(x=2:4,size=3,replace=T)
> sample(2:4,replace=T)
[1] 2 2 2
> sample(2:4,3,TRUE)
[1] 3 2 2
> sample(replace=T,x=2:4,size=3)
[1] 3 3 4
> sample(x=2:4,size=3,replace=T)
[1] 2 3 2





(4)ベクトルの参照

整数ベクトルによる要素参照

n番目の要素を1つ取り出すには、整数インデックスを指定します。Rは添字は「1」から始まることに注意してください。

a=101:105
a[1];a[2];a[3];a[4];a[5]
a[0]
a[6]
> a[1];a[2];a[3];a[4];a[5]
[1] 101
[1] 102
[1] 103
[1] 104
[1] 105
> a[0]
integer(0)
> a[6]
[1] NA

a[0]は値なしの変数、要素外の正の添字が指定された場合、NAとなります。

n番目の要素を書き換えるには以下のようにします。

a=101:105; a[3] = 3;
a
> a
[1] 101 102 3 104 105

複数の要素をもつベクトルを要素指定に適用すると、対応する要素を持つベクトルを返します。負の数字の場合、その要素を除いたベクトルが返ります(負の整数と正の整数を混在させるとエラーになります。)

a = 101:105
a1 = a[c(2,4)] #2番目と4番目の要素を取り出してベクトルにする
a2 = a[c(-2,-4)] #2番目と4番目の要素を取り除く
a3 = a[4:8] #2番目と4番目の要素を取り除く
> a1
[1] 102 104
> a2
[1] 101 103 105
> a3
[1] 104 105 NA NA NA

which関数の利用

特定の条件を満たす要素のみを取り出す時は、which()関数で、引数でwhich関数を使うことが便利です。まずは使い方の例を示します。

a = 100:106
a1 = a[which(a==100)] #要素が100のみを取り出す
a2 = a[which(a%%2==0)] #要素偶数のみを取り出す
a3 = a[which(a%%100>1)] #100で割った余りが1より大きい
> a1;a2;a3
[1] 100
[1] 100 102 104 106
[1] 102 103 104 105 106

Rでは、割った余りは「%%」を用いることに注意してください。

関連して、整数商は「%/%」で計算できます。例えば, 17わる3は、5余り2ですが、以下のように計算できます。

17 %/% 3; 17 %% 3
[1] 5
[1] 2
さて、つづいて、which関数のカラクリを理解していきましょう。
まずベクトルに対して、比較演算子による論理演算を行うと、各要素に対して、論理演算を満たすものにはTRUEが、満たさないものにはFALSEが割り当てられた、論理型のベクトルが返ります。サイズは変わらないことに注意してください。

a = 100:106
a%%2==0
> a%%2==0
[1] TRUE FALSE TRUE FALSE TRUE FALSE TRUE
which関数は、実質的に引数として、論理値型のベクトルに対して、TRUEの要素インデックスを取り出していることがわかります。

#上につづき
which(a%%2==0) #which(c(T,F,T,F,T,F,T)に同じ
> which(a%%2==0)
[1] 1 3 5 7
最終的に、単なる「整数ベクトルによる参照」が行われていることがわかります。

#上につづき
a[which(a%%2==0)] #a[c(1,3,5,7)]に同じ
> a[which(a%%2==0)]
[1] 100 102 104 106

論理値による抽出

論理演算による抽出を、which関数を使わずに行ってみましょう。

まず1から20までの整数列をつくります。

n = 1:20
> n
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
同じサイズの論理値のベクトルを使うと特定の要素だけ取り出すことができます。n1とn2は奇数部分だけを取り出す例。n3は、3の倍数より1大きい数を取り出す例です。

n1 = n[c(T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F,T,F)]
n2 = n[c(T,F)] #リサイクル規則
n3 = n[c(T,F,F)] #リサイクル規則
> n1;n2;n3
[1] 1 3 5 7 9 11 13 15 17 19
[1] 1 3 5 7 9 11 13 15 17 19
[1] 1 4 7 10 13 16 19
c(T,F,T,F,…)というベクトルは、比較演算子を使って導出することもできます。

n = 1:20
n %% 2 == 1
[1] TRUE FALSE TRUE FALSE TRUE FALSE TRUE FALSE TRUE FALSE TRUE FALSE TRUE FALSE
[15] TRUE FALSE TRUE FALSE TRUE FALSE

これを使えば、よりスマートに、特定の要素を取り出すことが可能です。

n1 = n[n %% 2 == 1]
n2 = n[n %% 3 == 1]
> n1;n2
[1] 1 3 5 7 9 11 13 15 17 19
[1] 1 4 7 10 13 16 19





(5)ベクトルの演算

複数要素のベクトルに対して単一の値による演算を行う場合、全ての要素に同一の演算を適用した結果のベクトルが生成されます。要素数が同じベクトル同士が演算を行う場合、同一要素インデックス同士の演算が行われます。

dice=1:6
d1.= dice
d2 = dice-1
d3 = dice/2
d4 = dice * dice
d5 = dice %% 3 #3で割った余り
> d1;d2;d3;d4;d5
[1] 1 2 3 4 5 6
[1] 0 1 2 3 4 5
[1] 0.5 1.0 1.5 2.0 2.5 3.0
[1] 1 4 9 16 25 36
[1] 1 2 0 1 2 0
ベクトルのサイズが異なる場合の演算は、
短い方のベクトルの要素が繰り返し使われます(リサイクル演算)。

x = c(2,2,3,3,4,4)
y = c(0.1,0.2)
z1 = x + y
z2 = x * y
> z1
[1] 2.1 2.2 3.1 3.2 4.1 4.2
> z2
[1] 0.2 0.4 0.3 0.6 0.4 0.8





(6)配列

array関数

Rにおいて、多次元ベクトルを格納するフォーマットとして、「配列」を紹介します。2次元配列の場合、各要素はm行n列のマトリックスの中の要素として扱われます。dim属性に「c(m,n)」を指定することで、引数1の(一次元)ベクトルが、「m x n」のマトリックスに変換されます。この際、ベクトルの要素が、列を固定して、行から順に埋まてちきます。。「m行n列」の「mは縦、nは横」で、「縦 × 横」のマトリックスを左から順に埋めていくイメージでもいいです。

一次元ベクトルを2行3列の配列に変換

a = array(1:6,dim=c(2,3))
> a
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
array関数で生成したマトリックスは、「ベクトル」ではなく「配列」として扱われます。

#上につづき
is.array(a) #aは配列
is.vector(a) #aはベクトルではない
> is.array(a)
[1] TRUE
> is.vector(a)
[1] FALSE
dim属性の一方を「1」とした場合も、ベクトルではなく一次元の配列扱いとなります。内部的に行と列の区別があることに注意してください。

a1 = array(1:6,dim=c(1,6))
a2 = array(1:6,dim=c(6,1))
> a1
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 2 3 4 5 6
> a2
[,1]
[1,] 1
[2,] 2
[3,] 3
[4,] 4
[5,] 5
[6,] 6
#上に続き
is.array(a1);is.vector(a1)
is.array(a2);is.vector(a2)
> is.array(a1);is.vector(a1)
[1] TRUE
[1] FALSE
> is.array(a2);is.vector(a2)
[1] TRUE
[1] FALSE
a[i,j]でi行 x j列の値を返します。また、a[i,]はaのi行目の要素群を、a[,j]はaのj列目の要素群を、ベクトルとして返します。これらの操作は、結果的に、配列をベクトルに変換していることに注意してください。

#上につづき
a[2,1] #2行1列目の要素
a[2,3] #2行3列目の要素
a[2,] #2行目の要素群
a[,3] #3列目の要素群
a[5] #一次元ベクトルに変換した際の5番目の要素
> a[2,1]
[1] 2
> a[2,3]
[1] 6
> a[2,]
[1] 2 4 6
> a[,3]
[1] 5 6
> a[5]
[1] 5

replicate関数(コマンドの複製)

replicate関数は、第二引数に示した関数(式)を、第一引数で指定した数だけ複製し、全ての出力を返します。

a1 = replicate(3, 1+1) #1+1の結果を3回繰り返しベクトルへ
a2 = replicate(10,sample(1:6,1)) #サイコロの無作為抽出を10回繰り返す
is.array(a2) #aは配列ではなく、単なる(一次元)ベクトル
[1] 2 2 2
[1] 4 3 4 6 3 3 5 2 2 3
[1] FALSE
返り値ベクトルの要素数(m)が1よりも大きい関数をn回replicateすると、結果は「m x n」の配列となります。

a = replicate(10,sample(1:6,size=2))  
is.array(a) #aは配列
> a
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 2 5 4 2 2 1 6 3 1 6
[2,] 1 1 6 6 1 2 2 1 2 2
> is.array(a)
[1] TRUE