プログラミング言語としてのR
言語仕様
関数型、オブジェクト指向、インタプリタ
開発環境
ユーザーインターフェース(UI):
- Windows:コマンドライン
- Mac:Terminal
- 共通:RGui(R Console + R Graphics)
作業ディレクトリの変更: setwd()
> getwd() #現在の作業ディレクトリが表示される [1] "/Users/tosh" > setwd("/Users/tosh/PROJECTS/R") #作業ディレクトリを変更する > getwd() [1] "/Users/tosh/PROJECTS/R"
コンソールの一行文字数の変更: options(“width”)
> options("width") $width [1] 62 > letters [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" [15] "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" > options("width"=80) > letters [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" [20] "t" "u" "v" "w" "x" "y" "z" > options("width") $width [1] 80
ヘルプ: help.start()
言語構造
注釈
“#”以降が注釈。Rubyと一緒。”/*…*/”や”//”は使えない。
構文
行末の”;”は不要。あってもよいし、一行に複数の文を記載する際は”;”で区切ることが出来る。
代入
C, Ruby, PHP, Javascript, Javaで一般的な’=’は使うことはできるが推奨されず'<-‘が使われる。
> a = b #これは使えるが推奨されない。 > a <- b #こちらが推奨される。bからaへ代入しますよという矢印の意味ですな。
定数
LETTERS, letters, month.abb, month.name, pieの5つ
> LETTERS [1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" [19] "S" "T" "U" "V" "W" "X" "Y" "Z" > letters [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" [19] "s" "t" "u" "v" "w" "x" "y" "z" > month.abb [1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec" > month.name [1] "January" "February" "March" "April" "May" "June" [7] "July" "August" "September" "October" "November" "December" > pi [1] 3.141593
変数(オブジェクト)
かなり変わっている。データ構造の最小単位が「配列」のようなイメージ。この単位をベクトルと呼んでいる。配列の要素に対して何かを一度に行う操作が基本になっている。なので、配列の要素に対してループで処理をするというのは邪道。Rubyで繰り返しをブロックで処理しているのが基本というような雰囲気。配列を最小単位にそれを2次元、3次元、、、多次元と一括処理できるような構造になっている。また正確には変数ではなくオブジェクト。
> a <- c(1,2,3,4,5) # [1,2,3,4,5]をaに代入。Rubyではa = [1,2,3,4,5]。cはcombineの意味。 > a #aの中身を表示 [1] 1 2 3 4 5 > a^2 #aの二乗を配列のそれぞれの要素に対して一括処理 [1] 1 4 9 16 25 > mean(a) #aの要素の平均 [1] 3
Rは大文字と小文字を区別する
予約語: break, else, for, function, if, in, next, repeat, return, while, FALSE, TRUE
→ これらは変数名(オブジェクト名)として使えない。
値の種類(class)
- 実数(numeric): 整数(Integer), 倍精度浮動小数点(Double), NaN(Not a Number, 非数値), Inf(Infinitive, 無限大)
> 0/0 #不定、数ではない [1] NaN > 1/0 #無限大 [1] Inf
整数と実数を特に区別しない。型を整数にしたい場合は関数as.integer()で変換
- 複素数(complex)
- 文字(character)
- 論理(logical): TRUE, FALSE, NA(Not Availabe); T, FにTRUE, FALSEが予め代入されている
> NA #データ欠損 [1] NA > T [1] TRUE > F [1] FALSE
- NULL
オブジェクトの種類
値の集合をベクトル(vector)、マトリックス(matrix)、データフレーム(data.frame)、配列(array)、リスト(list)の形式で一気に扱える。
- ベクトル
通常の感覚で言うところの「配列」。1つのベクトルの要素は単一の型よりなる必要がある。> a <- c(1,3,5,7,9) > b <- c("apple", "orange", "grape", "others")
オブジェクトの型はclass()関数で得ることが出来る。
> a #aの内容を表示 [1] 1 3 5 7 9 > class(a) #aの型はnumeric [1] "numeric" > b #bの内容を表示 [1] "apple" "orange" "grape" "others" > class(b) #bの型はcharacter [1] "character" > c <- c(1,3,5,"apple", "orange") #数値と文字列を同時に放り込むと.. > class(c) #文字列になっている! [1] "character" > c #1,3,5もダブルクオーテーションで囲まれて文字列になっている [1] "1" "3" "5" "apple" "orange"
通常の意味での数値配列に関しては色々な種類を簡単に生成できるようになっている。
> 2:7 #2から7までの1ずつの等差数列 [1] 2 3 4 5 6 7 > 5:-5 #5から-5までの-1ずつの等差数列 [1] 5 4 3 2 1 0 -1 -2 -3 -4 -5 >c(5:-5) #関数c()を使っても同様にできる [1] 5 4 3 2 1 0 -1 -2 -3 -4 -5 > seq(2, 10, by=1.5) #等差数列生成関数seq() [1] 1.00 3.25 5.50 7.75 10.00 > seq(1, 10, length=5) #1から10 までを等分割した要素数5のベクトル生成 [1] 2.0 3.5 5.0 6.5 8.0 9.5 > rep(3,5) #繰返し関数rep() [1] 3 3 3 3 3 > rep(1:4, 2) [1] 1 2 3 4 1 2 3 4 > rep(1:3, length=8) #(1 2 3)を要素数が8になるまで反復生成 [1] 1 2 3 1 2 3 1 2 > rep(1:4, each=2) [1] 1 1 2 2 3 3 4 4 > rep(1:4, c(2,1,2,1)) [1] 1 1 2 3 3 4 > runif(5) #乱数生成関数runif()。区間(0,1)上の一様分布乱数。引数の5は作成要素数 [1] 0.06487694 0.47683656 0.26286723 0.92059030 0.71073832 > rnorm(5) #乱数生成関数rnorm()。平均0,分散1の正規分布乱数。 [1] -0.58240284 0.23338618 -0.43588939 -1.90926106 0.05132192
- マトリックス
同じ種類の値(実数なら実数だけ、文字列なら文字列だけ)を要素に持つ2次元配列 - データフレーム
異なる種類の値(実数と文字列の混在など)を要素に持つ2次元配列 - 配列
普通の言語でいう配列とは全くイメージが違う。形式が同一のシートを複数持つExcelファイルと思えば良い。あるいは同一の構造を持つテーブルを複数持つデータベースのようなイメージ。3次元データ。 - リスト
オブジェクト指向言語におけるオブジェクトに含まれるデータ(値)とメソッド(振る舞い)のうち、データ部分のみを持つオブジェクトといった雰囲気。つまり、上記のベクトル、マトリックス、配列、リストを組み合わせて自由に1つのリスト内に要素として代入することが可能。> c <- list(c(1:8), c("A","B"), matrix(1:12,2,6))
オブジェクトの表示: objects()
オブジェクトの削除: rm()
全てのオブジェクトの削除: rm(list=ls(all=TRUE))
演算子
Rで特殊なのは上記のX^2のように配列(ベクトル)の要素に対して1つずつ演算を行い、結果を配列(ベクトル)として返すのが一般的であること。
- 絶対値、abs()
- 符号、sign()
> sign(c(1, 2, -3, 3, -1, -100)) [1] 1 1 -1 1 -1 -1
- 平方根、sqrt()
- 切上げ、ceiling()
- 切捨て、floor()
- 四捨五入、round()
- 対数、log(), log10(), log2() #底がそれぞれe, 10, 2
- 指数、exp()
配列操作(ベクトル操作)
-
結合、c()
> c(c(1,2,3), c(4,5,6)) [1] 1 2 3 4 5 6
-
一意化、unique()
> unique(c(1,2,3,5,2,3,5,3)) [1] 1 2 3 5
- 数え上げ、table()
> table(c('a','a','a','b','b','c')) a b c 3 2 1
- 要素数、length()
- 最小値、min()
- 最大値、max()
- 合計値、sum()
- 平均値、mean()
- 分散、var()
- 不偏標準偏差、sd()
標準ファイル I/O、読み込み、書き込み
- CSV読込み
csvファイルはread.csv()関数を用いて読込む
Excel由来のcsvファイルを読込む際の注意点> a <- read.csv("/Users/tosh/R/Data/data.csv") #Macだとこんな感じ > a <- read.csv("C:\Documents and Settings\tosh\My Documents\R\Data\data.csv") #Windowsだとこんな感じ > class(a) #オブジェクトの属性(データ形式)の確認にはclass()を用いる。 [1] "data.frame" #読み込んだデータはdata.frameになっている。
生存関数
-
> a <- read.csv("/Users/tosh/R/Data/survival.csv") > library(survival) #survivalライブラリの読込み必要。デフォルトでインストールはされている。 #生存日数カラム名がtime、状態(0 or 1)のカラム名がstatus、 #グループのカラム名がgroup、データオブジェクトがaの場合 > b <- survfit(Surv(time,status)~group, data=a) #表題(main)、X軸ラベル(xlab)、Y軸ラベル(ylab)を指定してグラフを書く > plot(b, main="Survival Curve", xlab="Time", ylab="Survival")