このノートブックでは、Rの基本的な使い方について説明します
あらゆるプログラミング言語において、データには型があります
例えば、Rのコンソール画面で1と打つと1と出力されますが
1
1
isという関数を使うと、これは"numeric"という型を持ち、また長さ1のvector(後述)でもあることがわかります
is(1)
- 'numeric'
- 'vector'
整数ではなく、小数点以下の数字も含んだ値(不動小数点数)もnumericです
is(2.1)
- 'numeric'
- 'vector'
ただし1Lと打つと、これはinteger(整数)としての1を定義したことになります
is(1L)
- 'integer'
- 'double'
- 'numeric'
- 'vector'
- 'data.frameRowLabels'
数値データは様々な計算ができます
1 + 1 # 足し算
2
3 - 1 # 引き算
2
6 * 2 # 掛け算
12
4 / 2 # 割り算
2
2^5 # 2の5乗
32
log10(5) # 5の常用対数値
0.698970004336019
ダブルクオーテーション"で文字列をくくると、これはcharacterというデータ型になります
"SAKIGAKE"
'SAKIGAKE'
is("SAKIGAKE")
- 'character'
- 'vector'
- 'data.frameRowLabels'
- 'SuperClassMethod'
is(1) # 1は数値
- 'numeric'
- 'vector'
is("1") # ""で囲むと文字列
- 'character'
- 'vector'
- 'data.frameRowLabels'
- 'SuperClassMethod'
numericとcharacter同士は計算することができません
ただし例外的に、paste関数では文字列も数値も扱えます
このようにデータの型の違いによって、関数の挙動が異なるので、注意が必要です
try(1 + "1") # 数値と文字列を足すことはできない
Error in 1 + "1" : 二項演算子の引数が数値ではありません
paste0("SAKIGAKE", "5") # 文字列同士を連結することはできる
'SAKIGAKE5'
paste0("SAKIGAKE", 5) # paste0関数の仕様で、文字列と数値を連結することはできる
'SAKIGAKE5'
論理値TRUE/FALSEはlogicalというデータ型になります
TRUE
TRUE
is(TRUE)
- 'logical'
- 'vector'
FALSE
FALSE
is(FALSE)
- 'logical'
- 'vector'
数値や文字列が等しい(==)場合、TRUEを返します
1 == 1 # これはTRUE(==は同じという意味)
TRUE
逆に等しくない場合はFALSEを返します
1 == 2 # これはFALSE
FALSE
"SAKIGAKE" == "SAKIGAKE" # これはTRUE
TRUE
"SAKIGAKE" == "CREST" # これはFALSE
FALSE
!=(等しく無い)と書く事でTRUE/FALSEを反転させた結果を得ることができます
"SAKIGAKE" != "CREST" # これはTRUE(!=は違うという意味)
TRUE
最後に、factor(因子)というデータ型を説明します
これは、以下のように同じ値が複数回出てくるベクトル(後述)の表現としてよく使われます
JST <- factor(c("SAKIGAKE", "SAKIGAKE",
"CREST", "CREST", "CREST",
"ACT-X", "ACT-X", "ACT-X"))
nlevels関数で、3種類の値が含まれていることがわかります
nlevels(JST) # 3つある
3
その三種類の値は具体的に以下のようなものだとわかります
levels(JST) # SAKIGAKE, CREST, ACT-Xがある
- 'ACT-X'
- 'CREST'
- 'SAKIGAKE'
因子を使う上で注意する必要がある点は、as.numericで数値になってしまう点です
文字列が数値化された場合と異なり、ただの通し番号1,2,3...として数値化されるので注意したいです
as.numeric("123456")
123456
as.character(JST) # 因子を文字列に変換する
- 'SAKIGAKE'
- 'SAKIGAKE'
- 'CREST'
- 'CREST'
- 'CREST'
- 'ACT-X'
- 'ACT-X'
- 'ACT-X'
as.numeric(JST) # 因子が数値になる?(よくバグの原因になる)
- 3
- 3
- 2
- 2
- 2
- 1
- 1
- 1
データには構造があります
例えば、Rでは1は長さ1のベクトルとして表現されます
# スカラは長さ1のベクトル
is(1)
- 'numeric'
- 'vector'
ベクトルを定義して、値を後で参照することができます
# c()でベクトルを作成
A <- c(2, 3, 1)
B <- c(-2, 1, -2)
# 各要素へのアクセス, Rは1-origin
A[1]
2
A[2]
3
A[3]
1
A[4] # 要素にないとNAになる
<NA>
ベクトルに対して、以下のように各種関数が既に用意されています
# 最大値、最小値、平均値、中央値
max(A)
min(A)
mean(B)
median(B)
3
1
-1
-2
# 要素ごとの掛け算(他の言語と違うところ)
A * B
- -4
- 3
- -2
# ベクトル同士の内積
A %*% B
-3 |
文字列でもベクトルを作れます
# 文字例でもベクトル
C <- c("A", "B", "C", "A", "AA")
# Aがどこの場所にあるか
which(C == "A")
- 1
- 4
# lengthと組み合わせて使うことが多い
length(which(C == "A"))
2
同じ型のデータが二次元に配置された行列というデータ構造もあります
# matrix()で行列を作成
E <- matrix(runif(6), nrow=2, ncol=3)
E[1,]
- 0.260141981765628
- 0.988072237931192
- 0.0720403743907809
E[,2]
- 0.988072237931192
- 0.34279353893362
行列独自の関数が各種用意されています
# 行数、列数
nrow(E)
ncol(E)
dim(E)
2
3
- 2
- 3
# cbind、rbind
cbind(A, B)
rbind(E, A, B)
A | B |
---|---|
2 | -2 |
3 | 1 |
1 | -2 |
0.2601420 | 0.9880722 | 0.07204037 | |
0.7605977 | 0.3427935 | 0.62231624 | |
A | 2.0000000 | 3.0000000 | 1.00000000 |
B | -2.0000000 | 1.0000000 | -2.00000000 |
# 行レベルでの和、列レベルでの和・平均値
rowSums(E)
colSums(E)
rowMeans(E)
colMeans(E)
- 1.3202545940876
- 1.72570745740086
- 1.02073965547606
- 1.33086577686481
- 0.694356619147584
- 0.440084864695867
- 0.575235819133619
- 0.510369827738032
- 0.665432888432406
- 0.347178309573792
matrixは同じ型のデータだけが含まれている必要がありますが、データフレームを使えば、列ごとに違うデータ型を扱うことができます
例えば、irisデータでは、1-4列目はnumeric、5列目はcharacterのデータを含んでいます
# 行列は一つの型しか扱えない
# 複数の型(数値、文字、TRUE/FALSE、因子など)を扱いたいときはデータフレーム
data(iris)
head(iris)
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species |
---|---|---|---|---|
<dbl> | <dbl> | <dbl> | <dbl> | <fct> |
5.1 | 3.5 | 1.4 | 0.2 | setosa |
4.9 | 3.0 | 1.4 | 0.2 | setosa |
4.7 | 3.2 | 1.3 | 0.2 | setosa |
4.6 | 3.1 | 1.5 | 0.2 | setosa |
5.0 | 3.6 | 1.4 | 0.2 | setosa |
5.4 | 3.9 | 1.7 | 0.4 | setosa |
iris$Petal.Length # $で各列にアクセスできる
- 1.4
- 1.4
- 1.3
- 1.5
- 1.4
- 1.7
- 1.4
- 1.5
- 1.4
- 1.5
- 1.5
- 1.6
- 1.4
- 1.1
- 1.2
- 1.5
- 1.3
- 1.4
- 1.7
- 1.5
- 1.7
- 1.5
- 1
- 1.7
- 1.9
- 1.6
- 1.6
- 1.5
- 1.4
- 1.6
- 1.6
- 1.5
- 1.5
- 1.4
- 1.5
- 1.2
- 1.3
- 1.4
- 1.3
- 1.5
- 1.3
- 1.3
- 1.3
- 1.6
- 1.9
- 1.4
- 1.6
- 1.4
- 1.5
- 1.4
- 4.7
- 4.5
- 4.9
- 4
- 4.6
- 4.5
- 4.7
- 3.3
- 4.6
- 3.9
- 3.5
- 4.2
- 4
- 4.7
- 3.6
- 4.4
- 4.5
- 4.1
- 4.5
- 3.9
- 4.8
- 4
- 4.9
- 4.7
- 4.3
- 4.4
- 4.8
- 5
- 4.5
- 3.5
- 3.8
- 3.7
- 3.9
- 5.1
- 4.5
- 4.5
- 4.7
- 4.4
- 4.1
- 4
- 4.4
- 4.6
- 4
- 3.3
- 4.2
- 4.2
- 4.2
- 4.3
- 3
- 4.1
- 6
- 5.1
- 5.9
- 5.6
- 5.8
- 6.6
- 4.5
- 6.3
- 5.8
- 6.1
- 5.1
- 5.3
- 5.5
- 5
- 5.1
- 5.3
- 5.5
- 6.7
- 6.9
- 5
- 5.7
- 4.9
- 6.7
- 4.9
- 5.7
- 6
- 4.8
- 4.9
- 5.6
- 5.8
- 6.1
- 6.4
- 5.6
- 5.1
- 5.6
- 6.1
- 5.6
- 5.5
- 4.8
- 5.4
- 5.6
- 5.1
- 5.1
- 5.9
- 5.7
- 5.2
- 5
- 5.2
- 5.4
- 5.1
データフレームでは、長さがそろった異なるデータ型を列で連結しているイメージですが、型だけでなく長さもばらばらのようなデータに対してはリストを使います
# 行列で表現できないようなデータもリストで表現できる
G <- list(X = c(1,2,3),
Y = matrix(runif(9), nrow=3),
Z = TRUE)
G$X # $で各要素にアクセスできる
- 1
- 2
- 3
G$Y
0.15133665 | 0.2781774 | 0.5372107 |
0.76381942 | 0.4672621 | 0.2771339 |
0.07307319 | 0.2749806 | 0.1801808 |
G$Z
TRUE
3次元以上の配列はarrayという関数で扱うことができます
# 普段はあまり使わないが、3次元以上の行列(例: テンソル)を表現する時などに
H <- array(1:10, dim=c(1,2,3))
H[1,1,3]
5
複雑なデータ構造はstr関数で見るとわかりやすいです
str(G)
str(iris)
List of 3
$ X: num [1:3] 1 2 3
$ Y: num [1:3, 1:3] 0.1513 0.7638 0.0731 0.2782 0.4673 ...
$ Z: logi TRUE
'data.frame': 150 obs. of 5 variables:
$ Sepal.Length: num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
$ Sepal.Width : num 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
$ Petal.Length: num 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
$ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
$ Species : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
Rの各種関数が返す値は、実は上記のようなこれ以上分解できない(Atomicな)データ型を組み合わせただけにすぎません
x <- runif(10)
y <- runif(10)
lr <- lm(y ~ x)
str(lr)
List of 12
$ coefficients : Named num [1:2] 1.265 -0.971
..- attr(*, "names")= chr [1:2] "(Intercept)" "x"
$ residuals : Named num [1:10] 0.09016 0.05118 -0.36323 0.00554 0.12556 ...
..- attr(*, "names")= chr [1:10] "1" "2" "3" "4" ...
$ effects : Named num [1:10] -2.02479 0.58034 -0.37784 -0.00696 0.11571 ...
..- attr(*, "names")= chr [1:10] "(Intercept)" "x" "" "" ...
$ rank : int 2
$ fitted.values: Named num [1:10] 0.475 0.591 0.741 0.784 0.837 ...
..- attr(*, "names")= chr [1:10] "1" "2" "3" "4" ...
$ assign : int [1:2] 0 1
$ qr :List of 5
..$ qr : num [1:10, 1:2] -3.162 0.316 0.316 0.316 0.316 ...
.. ..- attr(*, "dimnames")=List of 2
.. .. ..$ : chr [1:10] "1" "2" "3" "4" ...
.. .. ..$ : chr [1:2] "(Intercept)" "x"
.. ..- attr(*, "assign")= int [1:2] 0 1
..$ qraux: num [1:2] 1.32 1.02
..$ pivot: int [1:2] 1 2
..$ tol : num 1e-07
..$ rank : int 2
..- attr(*, "class")= chr "qr"
$ df.residual : int 8
$ xlevels : Named list()
$ call : language lm(formula = y ~ x)
$ terms :Classes 'terms', 'formula' language y ~ x
.. ..- attr(*, "variables")= language list(y, x)
.. ..- attr(*, "factors")= int [1:2, 1] 0 1
.. .. ..- attr(*, "dimnames")=List of 2
.. .. .. ..$ : chr [1:2] "y" "x"
.. .. .. ..$ : chr "x"
.. ..- attr(*, "term.labels")= chr "x"
.. ..- attr(*, "order")= int 1
.. ..- attr(*, "intercept")= int 1
.. ..- attr(*, "response")= int 1
.. ..- attr(*, ".Environment")=<environment: R_GlobalEnv>
.. ..- attr(*, "predvars")= language list(y, x)
.. ..- attr(*, "dataClasses")= Named chr [1:2] "numeric" "numeric"
.. .. ..- attr(*, "names")= chr [1:2] "y" "x"
$ model :'data.frame': 10 obs. of 2 variables:
..$ y: num [1:10] 0.565 0.642 0.378 0.789 0.962 ...
..$ x: num [1:10] 0.813 0.694 0.539 0.496 0.441 ...
..- attr(*, "terms")=Classes 'terms', 'formula' language y ~ x
.. .. ..- attr(*, "variables")= language list(y, x)
.. .. ..- attr(*, "factors")= int [1:2, 1] 0 1
.. .. .. ..- attr(*, "dimnames")=List of 2
.. .. .. .. ..$ : chr [1:2] "y" "x"
.. .. .. .. ..$ : chr "x"
.. .. ..- attr(*, "term.labels")= chr "x"
.. .. ..- attr(*, "order")= int 1
.. .. ..- attr(*, "intercept")= int 1
.. .. ..- attr(*, "response")= int 1
.. .. ..- attr(*, ".Environment")=<environment: R_GlobalEnv>
.. .. ..- attr(*, "predvars")= language list(y, x)
.. .. ..- attr(*, "dataClasses")= Named chr [1:2] "numeric" "numeric"
.. .. .. ..- attr(*, "names")= chr [1:2] "y" "x"
- attr(*, "class")= chr "lm"
lr$coefficients
- (Intercept)
- 1.26530432769542
- x
- -0.971465044455202
if-else構文で値によって、実行を切り替えることができます
SAKIGAKE <- "SAKIGAKE"
CREST <- "CREST"
if(SAKIGAKE == CREST){
print("Same!!!")
}else{
print("Different...")
}
[1] "Different..."
forやwhile構文で、設定した回数だけ繰り返し処理を行うことができます
I <- 1:20
for(i in 1:length(I)){
print(I[i])
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9
[1] 10
[1] 11
[1] 12
[1] 13
[1] 14
[1] 15
[1] 16
[1] 17
[1] 18
[1] 19
[1] 20
j <- 1
while(j <= 20){
print(I[j])
j <- j + 1
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9
[1] 10
[1] 11
[1] 12
[1] 13
[1] 14
[1] 15
[1] 16
[1] 17
[1] 18
[1] 19
[1] 20
何度も使う機能は関数として定義しておくと、再利用しやすくなります
jijou <- function(x){
if(is.numeric(x)){
x^2
}else{
stop("x is not numeric!!!")
}
}
jijou(3)
9
try(jijou("3"))
Error in jijou("3") : x is not numeric!!!
forやwhileよりも、より抽象的な書き方でapplyファミリー関数があります
apply(matrix(1:12, nrow=3), 1, mean)
- 5.5
- 6.5
- 7.5
apply(matrix(1:12, nrow=3), 2, var)
- 1
- 1
- 1
- 1
sapply(-3:3, abs)
- 3
- 2
- 1
- 0
- 1
- 2
- 3
lapply(list(A=1:3, B=matrix(1:12, nrow=3)), print)
[1] 1 2 3
[,1] [,2] [,3] [,4]
[1,] 1 4 7 10
[2,] 2 5 8 11
[3,] 3 6 9 12
- $A
- 1
- 2
- 3
- $B
A matrix: 3 × 4 of type int 1 4 7 10 2 5 8 11 3 6 9 12
applyに2つのパラメーターを指定したい
y <- "SAKIGAKE"
sapply(1:5, function(x, y){
cat(paste0(y, x, "\n"))
}, y=y)
SAKIGAKE1
SAKIGAKE2
SAKIGAKE3
SAKIGAKE4
SAKIGAKE5
- NULL
- NULL
- NULL
- NULL
- NULL
(d <- getwd()) # ()内の実行と、結果の出力を同時に行う
setwd("../") # 一つ上のディレクトリに移動
getwd()
'/Users/tsuyusakikouki/Desktop/elwood/Dev/SakigakeMTG2019/exercise1'
'/Users/tsuyusakikouki/Desktop/elwood/Dev/SakigakeMTG2019'
setwd(d) # 元いたところに戻る
getwd()
'/Users/tsuyusakikouki/Desktop/elwood/Dev/SakigakeMTG2019/exercise1'
# TSVのI/O
write.table(iris, "iris.txt")
iris.tsv <- read.table("iris.txt")
# CSVのI/O
write.csv(iris, "iris.csv")
iris.csv <- read.csv("iris.csv")
# バイナリデータのI/O
save(iris, file="iris.RData")
load("iris.RData")
# 全オブジェクトのI/O
save.image("20160806_SAKIGAKE.RData")
load("20160806_SAKIGAKE.RData")
system("ls", intern=TRUE) # UNIXコマンドをRから呼び出す
- '20160806_SAKIGAKE.RData'
- 'exercise1_Rintro.R'
- 'exercise1_Rintro.ipynb'
- 'iris.RData'
- 'iris.csv'
- 'iris.txt'
system("whoami", intern=TRUE) # ユーザー名
'tsuyusakikouki'
system("pwd", intern=TRUE) # getwd()と同じ
'/Users/tsuyusakikouki/Desktop/elwood/Dev/SakigakeMTG2019/exercise1'
system("Rscript --version", intern=TRUE) # Rscriptのバージョン
system("rm -rf iris*", intern=TRUE) # irisから始めるファイルは削除
sessionInfo()
R version 3.6.1 (2019-07-05)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS Catalina 10.15.1
Matrix products: default
BLAS: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRblas.0.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRlapack.dylib
locale:
[1] C/UTF-8/C/C/C/C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
loaded via a namespace (and not attached):
[1] Rcpp_1.0.3 digest_0.6.23 zeallot_0.1.0 crayon_1.3.4
[5] IRdisplay_0.7.0 repr_1.0.1 backports_1.1.5 jsonlite_1.6
[9] evaluate_0.14 pillar_1.4.2 rlang_0.4.2 uuid_0.1-2
[13] vctrs_0.2.0 IRkernel_1.0.2 tools_3.6.1 compiler_3.6.1
[17] pkgconfig_2.0.3 base64enc_0.1-3 htmltools_0.4.0 pbdZMQ_0.3-3
[21] tibble_2.1.3
Colaboratory ノートブックの操作について詳しくは、Colaboratory の概要をご覧ください。