井出草平の研究ノート

for文[R]

statisticsglobe.com

例1: Rでベクトルをループする

この例では、for-loopを使ってベクトル上をループする方法を説明する。

i in 1:10: iの中に1]から10までを代入していく i^2: 計算式

for(i in 1:10) {             # for文ヘッド
 
  x1 <- i^2                 # コードブロック
  print(x1)                  # 結果Print
}

結果。

[1] 1
[1] 4
[1] 9
[1] 16
[1] 25
[1] 36
[1] 49
[1] 64
[1] 81
[1] 100

例2: 文字ベクトルに対するループ処理

Rのforループは、通常の配列に対して反復するのではなく、オブジェクトの集合に対して反復することを理解することが非常に重要である。そのため、文字列のベクターに対してループをかけることができる。

文字型のベクターを作成。

x2 <- c("Max", "Tina", "Lindsey", "Anton", "Sharon")    # 文字ベクターの作成

nchar(i): 文字数を数える

for(i in x2) {        # 文字ベクターのループ関数のヘッド
 
  print(paste("The name", i, "consists of", nchar(i), "characters."))
}

結果。

[1] "The name Max consists of 3 characters."
[1] "The name Tina consists of 4 characters."
[1] "The name Lindsey consists of 7 characters."
[1] "The name Anton consists of 5 characters."
[1] "The name Sharon consists of 6 characters."

例3:for-loopの結果を加算してベクターに格納する

各forループの反復の出力をベクトルに連結するため、まず空のベクトルを作成する。

x3 <- numeric()  # 空のデータオブジェクトを作成する

for文を使って、出力値のベクトルを作る。

for(i in 1:10) {           # for分のヘッド
 
  x3 <- c(x3, i^2)      # コードブロック
}

結果。

x3                             # 結果Print
# [1]   1   4   9  16  25  36  49  64  81 100

例4:Rでのネストされたfor-Loop

for-loopはネストされたループでよく使用される。例4では、forループを別のforループの中に入れ子にする方法を紹介する。 まず、別の空のベクトルを作成する(例3と同様)。

x4 <- character()         # 空のデータオブジェクトを作成する

次のような入れ子のforループを使って、各ベクトル要素に2つの(異なる)アルファベットが含まれるベクトルを作成することができる。

for(i in 1:5) {       # 最初のfor-loopのヘッド
 
  for(j in 1:3) {     # ネストされたfor-loopのヘッド
 
    x4 <- c(x4, paste(LETTERS[i], letters[j], sep = "_"))  # コードブロック
  }
}
x4       # 結果Print

結果。

"A_a" "A_b" "A_c" "B_a" "B_b" "B_c" "C_a" "C_b" "C_c" "D_a" "D_b" "D_c" "E_a" "E_b" "E_c"

例5:論理的条件に基づくfor-loopのBreak

forループの中に論理的なif条件を指定し、それがTRUEになった場合にループの実行を停止させることができる。 この例では、i >=5 という条件を満たしたときにループを停止させる方法を説明する。if条件の中でbreak文を使う。

for(i in 1:10) {         # for-loopのヘッド
 
  x5 <- i^2             # コードブロック
  print(x5)               # 結果Print
 
  if(i >= 5) {            # 条件付きでfor-loopを停止する
 
    break                 # breakステートメントの使用
  }
}

結果。

[1] 1
[1] 4
[1] 9
[1] 16
[1] 25

例6:for-Loopの中でnext文を使い反復処理をスキップする

例5と同様にnext文でforループの繰り返しをスキップすることもできる。次のforループは、インデックス位置1、5、7でスキップされる。

for(i in 1:10) {                  # for-loopのヘッド
 
  if(i %in% c(1, 5, 7)) {      # 条件付きスキップ反復
 
    next                             # next文の使用
  }
 
  x6 <- i^2                       # コードブロック
  print(x6)                        # 結果Print
}

結果。

[1] 4
[1] 9
[1] 16
[1] 36
[1] 64
[1] 81
[1] 100

例7:データフレーム列に対するfor-Loop

この例では、データフレームの変数をループで処理する方法を説明する。まず、irisデータをロードしてみよう。

data(iris)  # irisのデータセットの読み込み
head(iris) 
#   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 1          5.1         3.5          1.4         0.2  setosa
# 2          4.9         3.0          1.4         0.2  setosa
# 3          4.7         3.2          1.3         0.2  setosa
# 4          4.6         3.1          1.5         0.2  setosa
# 5          5.0         3.6          1.4         0.2  setosa
# 6          5.4         3.9          1.7         0.4  setosa

この例のデータフレームには、アヤメの花に関する情報からなる5つの列が含まれています。iris_new1 という新しいデータフレームオブジェクトにデータを複製する。

iris_new1 <- iris  # irisデータセットの複製

ここで、for文の先頭でncol関数を使って、データフレームの列をループさせることができるforループの中では、論理的なif条件も使用している。

greplは文字ベクトルに一致させる関数(参考: https://www.delftstack.com/ja/howto/r/grepl-in-r/ , https://r-lang.com/grepl-in-r/)
ncol(iris_new1): 変数の数(列数)を数える
grepl("Width", colnames(iris_new1)[i]): colnames(iris_new1)=変数名の中から、"Width"の含まれるものに限定し iris_new1[ , i]: iris_new1のi列目 iris_new1[ , i] + 1000: 列に1000を加算

for(i in 1:ncol(iris_new1)) {                                # for-loopのヘッド
 
  if(grepl("Width", colnames(iris_new1)[i])) {         # 論理条件
 
    iris_new1[ , i] <- iris_new1[ , i] + 1000              # コードブロック
  }
}

更新されたデータフレーム。

head(iris_new1)  
#   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 1          5.1      1003.5          1.4      1000.2  setosa
# 2          4.9      1003.0          1.4      1000.2  setosa
# 3          4.7      1003.2          1.3      1000.2  setosa
# 4          4.6      1003.1          1.5      1000.2  setosa
# 5          5.0      1003.6          1.4      1000.2  setosa
# 6          5.4      1003.9          1.7      1000.4  setosa

例8:for-Loopを使った変数名の作成

例8では、forループの中で変数名を作成したり変更したりする方法を紹介する。もう一度、irisの元のデータフレームを複製しよう。

iris_new2 <- iris 

ここで、colnames と paste0 関数を適用して、データフレームの各列に新しい列名を作成することができる。

for(i in 1:ncol(iris_new2)) {                                # for-loopのヘッド
 
  colnames(iris_new2)[i] <- paste0("new_", i)    # コードブロック
}

結果。

head(iris_new2)
#   new_1 new_2 new_3 new_4  new_5
# 1   5.1   3.5   1.4   0.2 setosa
# 2   4.9   3.0   1.4   0.2 setosa
# 3   4.7   3.2   1.3   0.2 setosa
# 4   4.6   3.1   1.5   0.2 setosa
# 5   5.0   3.6   1.4   0.2 setosa
# 6   5.4   3.9   1.7   0.4 setosa

ごのように、データフレームの列には接頭辞 "new_"とデータフレーム内での位置の名前が付けられている。

例9:for-Loop内で複数のプロットを作成する場合

for-loopは、数行のコードで複数のプロットを効率的に描画したい場合に非常に便利である。例えば、irusデータフレームの各数値列のプロットを描きたい場合を考えてみよう。すると、次のようなRコードが使えます。

ncol(iris): 列数のカウント nrow(iris): 行数のカウント

for(i in 1:(ncol(iris) - 1)) {          # for-loopのヘッド
 
  plot(1:nrow(iris), iris[ , i])        # コードブロック
  Sys.sleep(1)                            # コード実行の一時停止
}

f1

先のRコードで作成した最終的なプロットを図1に示す。グラフを描画した後、1秒待つように指定していることに注意してほしい。これは、GIFファイルを作成する場合にも有効である。 for-loopでデータをプロットするための、より高度なチュートリアルを作成した。このチュートリアルはggplot2パッケージ(Rのグラフィックのための非常に強力なパッケージ)についてもカバーしている(https://statisticsglobe.com/print-ggplot2-plot-within-for-loop-in-r)。

例 10: リストオブジェクトを通るfor-Loop

これまでの例では、ベクターやデータフレームにfor-loopを適用してきた。この例では、リストオブジェクトの操作のためにfor-loopをどのように書き、使用するかを紹介する。 まず、リストの例を作成する。

my_list <- list(1:5,                  # サンプルリストの作成
                letters[3:1],
                "XXX")
my_list           # print例のリスト
# [[1]]
# [1] 1 2 3 4 5
# 
# [[2]]
# [1] "c" "b" "a"
# 
# [[3]]
# [1] "XXX"                                                 

このリストは3つの異なるリスト要素から構成されている。length関数を使って、リスト上をループすることができる。

for(i in 1:length(my_list)) {                 # for-loopのヘッド
 
  my_list[[i]] <- rep(my_list[[i]], 3)      # コードブロック
}

結果。

my_list                                                # Print アップデートしたリスト
# [[1]]
# [1] 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5
# 
# [[2]]
# [1] "c" "b" "a" "c" "b" "a" "c" "b" "a"
# 
# [[3]]
# [1] "XXX" "XXX" "XXX"

各リストの要素を3回複製している。