[Work/Class/Rの基礎とデータ処理/r_basic]

Rの基本と配列(array,list)の取り扱い,制御構造,関数

変数

変数宣言や変数の型宣言は要らない

Rの変数を宣言する時に,整数型や文字列型等の型宣言は要らない.また変数であることを宣言するキーワードもない.

代入のための演算子には<-を用いる.

a <- 5 # 変数に代入.宣言は必要ない.
b <- 8
a + b # 最後に実行したものが表示される.

#の後にスペース一つ開けて文字を書き始めるとコメント

Rは半分関数型言語のため,何かの式を実行した時には必ず値が返る

a <- 5
b <- 8
c <- b - a 
c

変数の名前を書くと実行したことになって表示される

print関数を使っても良い

printを使うと,多次元配列の時何行目何列目のprintなのかも表示してくれる.

a <- 5
b <- 8
c <- b - a 
print(c)

記はスカラ値で,1番目の要素のみなので,数字の前に[1]と出力される

変数に関する規則でR独特なのは,「.」が,「オブジェクトインスタンスやクラスの中の要素」を表すのではなく,普通の変数名に使える文字として使えること

y.a <- 3
y.b <- 4
print(y.a + y.b)

上記は「yというオブジェクトインスタンスの中のaオブジェクト」ではなく,「y.aという変数名」として扱われる

普通のプログラミング言語では,単語をつないだ変数名の場合,
キャメルバック(ラクダの背中)形式: sumOfThisArray のように,最初以外の単語の頭文字を大きくする
アンダースコアで繋ぐ: sum_of_this_array
の方法があるが,Rの場合はアンダースコアで繋ぐ形式を「.」に置き換えたもの,と言うことができる.

ifブロックやforブロックの中の変数(スコープ)

Rはpythonと同じくfor文のif文のブロックスコープを持たない.

for (i in 1:10) {
  if (i == 1) {
    x <- i
  } else {
    x <- x + i
  }
}
print(x)

xという変数は,上のfor文のブロック内で初めて出てきた変数なので,普通の感覚から言うとfor文ブロックの実行が終わった後には破棄されるが,Rの場合Pythonと同じくブロックの外からでもアクセスできる.

やはりPythonと同じく関数の変数スコープはある.

ブロックスコープがない代わりに,環境というオブジェクトのようなものがあり,そこに変数をくっつけることで,同じ名前の変数を増やすことができる.

インデックス

普通のプログラミング言語のインデックスは0から始まるが,Rは1からが原則.例えばfor文は,

for (i in 1:10){
    print(i)
}

となり,1から10までの値が出る.

範囲指定でコロン「:」を使っていることに注意.
x:yという範囲指定の時 x以上,y以下の値が出る.
10:1だと,10以下,1以上

配列array

固定長配列でC言語の配列と同じ.pythonでいう所のnumpy配列である.

Rではベクタやマトリクスと呼ばれることが多いことからわかるように,基本的にこれらの計算用であり,文字列のarrayはあまり使わない.

1次元配列

Rでは1次元配列はVector, ベクトルと呼ぶことが多い.
例えば10要素を全部0.0で初期化したければ,

x <- array(0.0, dim=c(10))
print(x)

と書くこともできる.

c(おそらくcolumnの略)関数に注意.1行目しかないので,printでは配列の前に[1]が表示される.

x <- array(1:10, dim=c(10))
print(x)

上記は,次元が1次元で10要素ある配列を作り,1~10まで順に入れていけ,という配列の作り方.

前述のインデックスでわかる通り,配列のインデックスは1〜なので,

x <- array(10:1, dim=c(10))
print(x[1])

はarray xの「先頭の次」の要素ではなく,「先頭の要素」を指す.

配列の結合c関数

# c関数で結合できる.c関数は非破壊的なので,編入に代入して受ける.

x <- array(3:1, dim=c(3))
y <- array(6:4, dim=c(3))
w <- c(x, y)
print(w)

配列の要素の置き換えreplace関数

replace関数は,やはり非破壊的なので,変数に代入して受ける.

x <- array(3:1, dim=c(3))
y <- replace(x, 2, 4) # 配列xの2番目の要素を,4で置き換える
print(y)

replaceはまとめて指定することができる.
1番目と3番目の要素をそれぞれ5と7で置き換えるという処理の場合,

x <- array(1:3, dim=c(3))
y <- replace(x, c(1, 3), c(5, 6))
print(y)

2次元配列と連結

x <- array(1:6, dim=c(3, 2))
print(x)

は3行2列の配列になる.

ここにきて,行と列があるので,print関数で出力される何番目の行か,何番目の列かの表示がうまく機能するようになる.

x <- matrix(1:6, nrow=3, ncol=2)
print(x)

のように,matrix関数を使っても同じことができる.つまり行列である.

2次元配列の各要素には,以下のようにアクセスする.

x <- matrix(1:6, nrow=3, ncol=2)
print(x)

print(x[2, ]) # 2行目を丸ごと
print(x[, 2]) # 2列目を丸ごと

print(x[1, 2]) # 1行目2列目の要素
print(x[c(1,2), 2]) # 1,2 行目2列目の要素

print(x[c(1,3), c(1:2)]) # 1,3行目の1から2列目の要素

行列(2次元配列)の結合

rbind()関数(縦に結合),cbind()関数(横に結合),を用いる.

やはり非破壊的なので,結果を変数で受ける必要がある.

x <- matrix(1:6, nrow=3, ncol=2)
y <- matrix(7:12, nrow=3, ncol=2)

w = rbind(x, y) # 縦に結合
z = cbind(x, y) # 横に結合

print(w)
print(z)

配列list

もう一つ配列にはlistもある.

arrayは整数なら整数,実数なら実数というデータ型が決まっているが,listはなんでも入れられるため,複数のデータ型をまとめるデータ型という基準で作られているようだ.C言語の構造体に近い扱いをするべきだろうか?

x <- list(8, array(1:4, dim=c(2, 2)), "文字列")
print(x)

上記のコードのprint関数の出力は,以下のようにバラバラに出てくる.やはり構造体っぽい.

[[1]]
[1] 8

[[2]]
     [,1] [,2]
[1,]    1    3
[2,]    2    4

[[3]]
[1] "文字列"

制御構造

if文

if文の中で普通に==,!=,>=,>などの通常の比較演算子を使うことができる.

elseの前は改行してはいけないという規則があるので注意.

a <- 3
if (a == 1){
    print('aはいち!')
}else if (a < 2){
    print('aは2より小さい')
} else if(a < 2){
    print('aは3より小さい')
} else {
    print('それ以外')
}

等号不等号は,だいたい他の言語と同じ.論理積と論理和はそれぞれ&&||

ちなみにBooleanはTRUEFALSE

a <- 2
b <- 4
(a < 3) && (a >1)  #TRUEが返る

switch文

Rにはpythonと違いちゃんとswitch文がある

ただし構文が非常に特殊.関数オブジェクト的に考えて
'マッチ文' = 処理式
になる.

a <- 3
switch(a,
       '1' = print('いち!'),
       '2' = print('に!'),
      '3'=print('さん!'),
       print('それ以外!')
      )

上記のように整数にマッチさせる時でもシングルクォーテーションかダブルクォーテーションで囲む必要がある.

関数の定義と呼び出し

function()関数で関数オブジェクトを作って変数に代入する形.

func <- function(x){ 
    ans <- x ** 2
    return(ans) # returnはキーワードではなく関数であることに注意
}

# 関数オブジェクトの呼び出し
a <- func(4)
print(a)