ご挨拶
今回から、Rの使い方についてポチポチ書いていきます。
※独学の部分も多いので、修正点等あればお気軽にコメントでのご指摘をお願いします……。
前の記事はコチラ
【都市・観光情報学でのRマニュアル】1 データ型
【都市・観光情報学でのRマニュアル】2 データ構造
1. 基本演算
・ 数値演算
| 演算子 | 説明 |
|---|---|
+ |
足し算(2 + 3→5) |
- |
引き算(5 - 3→2) |
* |
掛け算(2 * 3→6) |
/ |
割り算(6 / 2→3) |
^ |
べき乗(2 ^ 3→8) |
%% |
剰余(5 %% 3→2) |
%/% |
整数除算(5 %/% 3→1) |
・ 比較演算
== |
等しい(2 == 2→TRUE) |
!= |
等しくない(2 != 3→TRUE) |
< |
小なり(2 < 3→TRUE) |
> |
大なり(2 > 3→FALSE) |
<= |
以下(2 <= 2→TRUE) |
>= |
以上(3 <= 2→FALSE) |
2. 特殊な値
RにはNAやNULLといった特殊な値が存在する。
これらはエラーや思わぬ処理結果につながることがあるので、種類を見極めて除外したり置換したりする必要がある。
補足
使い方によっては余計なエラーが出るのを防ぐことも出来る。特徴と挙動を把握しておくのが肝心
・ NA(Not Available)
いわゆる欠損値。ベクトルやデータフレームの中であるはずだが観測されなかったデータを指す。
補足
一般的にはNA(真理値:logical)で表されるが、NA_REAL_(実数:double)やNA_integer_(整数:integer)などデータ型に依存した記号も用意されている。
・ NULL(null)
未定義値/非存在値。そもそも存在しないデータを指す。
・ NaN(Not a Number)
非数値。数学的に定義されていない値を指す。
例:0 / 0, Inf - Inf
・ Inf(infinity)
無限大
補足
あまり使うことはないが、重み付きネットワークの最短経路問題を解くアルゴリズムであるベルマン―フォード(Bellman-Ford)法では各ノードの初期最短経路をInfに設定する。
Tips:NAとNULLの扱われ方の違い
# ---NAの場合---
vec <- c(1, 2, 3, NA, 5)
vec
# [1] 1 2 3 NA 5
# vecの要素数を取得
length(vec)
# [1] 5
# ---NULLの場合---
vec <- c(1, 2, 3, NULL, 5)
vec
# [1] 1 2 3 5
# vecの要素数を取得
length(vec)
# [1] 4
このように、NAは欠損値としてあるものとして扱われる。一方で、`NULL
は元からないものとして扱われれる。
Tips:予約語と組込み定数
Rには変数として上書き不可能な予約語と、上書きは可能だが推奨されない組込み定数が存在する。
1. 予約語
-
制御構文
if,else,while,function,for,in,next,break -
真理値
TRUE,FALSE -
特殊な値
NA,NULL,Inf,NA_integer,NA_real_,NA_comprex_,NA_character_
2. 組込み定数(代表的なもの)
-
円周率π
pi -
真理値
TRUE(= TRUE),F(= FALSE)
3. 条件分岐
この節では、if文を使った条件分岐の構文について扱う。
条件が1つの場合は、
if (条件式) {
# 条件式が TRUE のときに実行する処理
} else {
# 条件式が FALSE のときに実行する処理
}
else以下は省略可能。
なお、条件が複数の場合は以下のようになる。
if (条件式1) {
# 条件式1が TRUE のときに実行する処理
} else if (条件式2) {
# 条件式2が TRUE のときに実行する処理
} ...
4. ループ
・ forループ
決まった回数の処理を繰り返すときに利用する。
ベクトルの長さが繰り返し回数になる。
for (variable in vector) {
# 繰り返す処理
}
vectorの1つ目から順番に、variableに要素が代入されていく。
for文の使い方の例
# for文の使い方
result <- numeric(6)
for (i in 1:6) {
result[i] <- i * 2
}
result
# [1] 2 4 6 8 10 12
・ whileループ
指定した条件がTRUEである限り処理を繰り返す。
while(条件式){
# 繰り返す処理
}
注意
無限ループにならないよう、繰り返し処理の中で変数を変化させる必要がある。
while文の使い方
# while文の使い方
result <- numeric(6)
t <- 1
while(t <= 6){
result[t] <- t * 2
t <- t + 1 # この操作を入れないとt == 1のままなので無限ループになってしまう!
}
result
# [1] 2 4 6 8 10 12
・ repeatループ
終了条件をループ内に自分で設定する無限ループ
repeat{
# 繰り返す処理
# 終了条件
break
}
注意
終了条件を間違えるとループ回数が0や無限になるので注意が必要
repeat文の使い方
# repeat文の使い方
result <- numeric(8)
t <- 1
repeat{
result[t] <- t * 2
t <- t + 2
if (t * 2 > 12) break
}
result
# [1] 2 4 6 8 10 12 0 0
・ 制御構文
ループの進行を制御するために、いくつかの制御構文が存在する。
-
next
現在の繰り返し処理をスキップし、次の繰り返し処理を行う。 -
break
ループを強制終了する。
制御構文の使い方
# 制御構文の使い方
result <- numeric(8)
for (t in 1:8) {
if (t == 3) next t = 3のとき、処理をスキップ
if (t > 6) break t > 6のとき、処理を強制終了
result[t] <- t * 2
}
result
# [1] 2 4 0 8 10 12 0 0
Tips:ループは処理が遅い
Rのループは仕様上、処理速度が大変遅い。
データサイズが大きい時は特に処理速度の遅さが顕著になるので、ベクトルやデータフレームを利用して出来る限りループの使用回数を減らすとよい。
ループ処理とベクトル操作の処理速度の比較
今回は、2を先頭に1,000万個の偶数を要素とするベクトルを取得する際の処理速度を比較する。
# forを使ったときの処理速度
start_time <- Sys.time()
vec <- numeric(1e7)
for (i in 1:1e7) {
vec[i] <- i * 2
}
end_time <- Sys.time()
elapsed <- round(as.numeric(difftime(end_time, start_time, units = "secs")), 4)
# 処理にかかった時間(secs)
elapsed
# [1] 0.308
# 変数の削除(環境を初期化して正確に処理速度を計測するため)
rm(list = ls())
# ベクトルを使ったときの処理速度
start_time <- Sys.time()
vec <- c(1:1e7)
vec <- vec * 2
end_time <- Sys.time()
elapsed <- round(as.numeric(difftime(end_time, start_time, units = "secs")), 4)
# 処理にかかった時間(secs)
elapsed
# [1] 0.1612
このように、×2という単純な計算でもデータサイズが大きいとループ処理は約1.9倍の処理時間がかかる。
Harvesin法(緯度経度から2点間の距離を求めるアルゴリズム)など、複雑な計算を繰り返し行う場合はさらにその差が顕著になる。
次の投稿
実際にデータ処理をする際のディレクトリ操作について書くと思います。
データのインポートやエクスポート関連です。
>書きました。
【都市・観光情報学でのRマニュアル】 4 ディレクトリ操作