R の For ループとリストと行列の例

⚡ スマートサマリー

R言語のforループは、シーケンスの各要素に対してコードブロックを一度ずつ実行します。シーケンスがベクトル、リスト、行列のいずれであっても同様です。このチュートリアルでは、それぞれのシーケンスについて繰り返し説明し、ベクトル化されたコードの方が適している場合を示します。

  • 🔁 コア構文: for (i in vector) { expression } は、各要素を順番に i に割り当て、本体を実行します。
  • ???? 任意のオブジェクト: 同じ構文で、ベクトル、リスト、データフレームの列セット、または行列の行を走査できます。
  • 🧮 ネストされたループ: 行列には2つのループが必要で、外側のループは行用、内側のループは列用です。
  • 🛑 フロー制御: breakはループを完全に抜け出し、nextは現在の要素のみをスキップします。
  • ベクトル化を最初に行う: 組み込みのベクトル化演算とapply関数群は、明示的なループよりも高速で、記述時間も短くなります。
  • ⚠️ 安全な手順: オブジェクトが空の場合に正しく動作しないため、1:length(x)ではなくseq_along(x)を使用してください。

Rのリスト行列におけるforループ

A forループ シーケンスの各要素に対してコードブロックを一度繰り返します。そのシーケンスは、ベクトル、リスト、データフレーム、行列、またはRが反復処理できるその他のオブジェクトです。Rは大文字と小文字を区別するため、キーワードは常に小文字です。 また、本文が複数行にわたる場合は、必ず波括弧が必要です。

Rにおけるforループの構文

for (i in vector) {
    Exp
}

ここでは、

R ベクトル内のすべての変数をループし、exp 内に記述された計算を実行します。

R の For ループ
R の For ループ

いくつかの例を見てみましょう。

R の For ループの例 1: ベクトルのすべての要素を反復処理し、現在の値を出力します。

# Create fruit vector
fruit <- c('Apple', 'Orange', 'Passion fruit', 'Banana')
# Create the for statement
for ( i in fruit){ 
 print(i)
}

出力:

## [1] "Apple"
## [1] "Orange"
## [1] "Passion fruit"
## [1] "Banana"

R の For ループの例 21から4までのすべての整数を二乗し、結果をリストに格納します。

# Create an empty list
list <- c()
# Create a for statement to populate the list
for (i in seq(1, 4, by=1)) {
  list[[i]] <- i*i
}
print(list)

出力:

## [1]   1  4 9 16

for ループは機械学習の作業で役立ちます。正則化パラメータを調整するということは、多くの候補値をテストし、ping 損失関数を最小化する関数であり、forループはその範囲を走査する最も簡単な方法です。

forループでbreakとnextを使用する方法

2つのキーワードがforループの通常の処理を中断します。

  • 破る ループを即座に抜け出し、残りの要素をすべてスキップします。
  • 次の 現在の要素のみを放棄し、次の要素に移ります。
fruit <- c('Apple', 'Orange', 'Passion fruit', 'Banana')

# break: stop at the first match
for (i in fruit) {
    if (i == 'Passion fruit') {
        print('Found it, stopping here')
        break
    }
    print(i)
}

# next: skip one element and carry on
for (i in fruit) {
    if (i == 'Orange') next
    print(i)
}

入れ子になったループでは、breakとnextはそれらを含む最も内側のループのみに作用します。行列の例で両方のループをそのままにするには、フラグ変数を設定し、外側のループでもそのフラグをテストします。

インデックスには seq_along() を使用してください。 for (i in 1:length(x)) という記述は一見無害に見えますが、空のオブジェクトでは失敗します。なぜなら、1:0 はシーケンス 1, 0 を生成し、ループが 2 回実行されるからです。seq_along(x) は代わりに空のシーケンスを返すため、ループは正しくスキップされます。

for (i in seq_along(fruit)) {
    cat(i, fruit[i], '\n')
}

リストに対するforループ

ローping リストの上での操作は、トイレとまったく同じように機能します。ping ベクトルと同様だが、各要素は異なる型を保持できる。

# Create a list with three vectors
fruit <- list(Basket = c('Apple', 'Orange', 'Passion fruit', 'Banana'), 
Money = c(10, 12, 15), purchase = FALSE)
for (p  in fruit) 
{ 
	print(p)
}

出力:

## [1] "Apple" "Orange" "Passion fruit" "Banana"       
## [1] 10 12 15
## [1] FALSE

行列に対するforループ

行列は行と列という2つの次元を持つため、すべてのセルを反復処理するには、行用の外側のループと列用の内側のループという2つのネストされたforループが必要です。

# Create a matrix
mat <- matrix(data = seq(10, 20, by=1), nrow = 6, ncol =2)
# Create the loop with r and c to iterate over the matrix
for (r in 1:nrow(mat))   
    for (c in 1:ncol(mat))  
         print(paste("Row", r, "and column",c, "have values of", mat[r,c]))  

出力:

## [1] "Row 1 and column 1 have values of 10"
## [1] "Row 1 and column 2 have values of 16"
## [1] "Row 2 and column 1 have values of 11"
## [1] "Row 2 and column 2 have values of 17"
## [1] "Row 3 and column 1 have values of 12"
## [1] "Row 3 and column 2 have values of 18"
## [1] "Row 4 and column 1 have values of 13"
## [1] "Row 4 and column 2 have values of 19"
## [1] "Row 5 and column 1 have values of 14"
## [1] "Row 5 and column 2 have values of 20"
## [1] "Row 6 and column 1 have values of 15"
## [1] "Row 6 and column 2 have values of 10" 

Rでデータフレームをforループで処理する

データフレームは列のリストなので、通常のforループは行ではなく列を走査します。通常はそれが望ましい動作です。

df <- data.frame(a = 1:5, b = 6:10, c = 11:15)

# Loop over the columns
for (col in names(df)) {
    cat(col, 'has mean', mean(df[[col]]), '\n')
}

二重括弧に注意してください。df[[col]] extracts は列をベクトルとして扱いますが、df[col] は mean() では処理できない 1 列のデータフレームを返します。

ローping 行にわたって。 行ごとの反復処理は可能ですが、Rは各パスで行をコピーするため、処理速度が遅くなります。

for (r in seq_len(nrow(df))) {
    cat('Row', r, 'sums to', sum(df[r, ]), '\n')
}

数千行を超えるデータの場合は、rowSums(df)、apply(df, 1, sum)、またはdplyrを使用することをお勧めします。 group_by() と summarise() パイプラインは、コピーすることなくすべて同じ作業を実行します。

Rにおけるforループとベクトル化の比較

Rはベクトル化された言語です。その演算子や関数のほとんどは、コンパイル済みのCコードにおいて既にベクトル全体に対して一度に作用します。ベクトル化された操作を要素ごとに繰り返す明示的なループは、より長く、より低速になります。

# Loop version
squares <- c()
for (i in 1:4) {
    squares[i] <- i * i
}

# Vectorized version, same result
squares <- (1:4)^2
仕事 ループ ベクトル化された等価物
要素ごとの算術演算 各要素について x * 2、x + y、x^2
列ごとに関数を適用する for over names(df) sapply(df, mean)
行ごとに関数を適用する seq_len(nrow(df)) を超える場合 apply(df, 1, sum)
結果リストを作成する for with list[[i]] <- … lapply(v, f)
条件付き再コーディング if と else を使用した for ifelse(cond, a, b)

ループが依然として正しい解決策である場合。 各イテレーションが前回の結果に依存する場合、外部サービスを呼び出したりファイルを書き込んだりする場合、または小さなオブジェクトに対して速度よりも明瞭さが重要な場合は、forループを使用してください。

ループ処理が必要な場合は、事前にメモリを割り当ててください。 ループ内でオブジェクトを拡張すると、Rはループのたびにそのオブジェクトをコピーします。まずはフルサイズで作成してください。

# Slow: the vector is reallocated on every pass
out <- c()
for (i in 1:1000) out[i] <- i^2

# Fast: allocated once
out <- numeric(1000)
for (i in 1:1000) out[i] <- i^2

R言語におけるforループ:クイックリファレンス

このチュートリアルで使用されるすべての構成要素は以下のとおりです。

DevOps Tools Engineer試験のObjective Code
ベクトルをループ処理する
for (i in v) { print(i) }
インデックスを安全にループ処理する
for (i in seq_along(v)) { print(v[i]) }
リストをループ処理する
for (p in my_list) { print(p) }
データフレームの列をループ処理する
for (col in names(df)) { print(mean(df[[col]])) }
行列をループ処理する
for (r in 1:nrow(m)) for (c in 1:ncol(m)) print(m[r, c])
早めにループから抜け出す
if (condition) break
1回の反復をスキップする
if (condition) next
出力を事前割り当てする
out <- numeric(n)

よくあるご質問

xが空の場合、1:length(x)はシーケンス1, 0を返し、存在しない要素に対してループが2回実行されます。seq_along(x)は空のシーケンスを返すため、ループは正しくスキップされます。

ループ自体に問題があるわけではありません。問題は、ループ内でオブジェクトを拡張することです。なぜなら、Rはループのたびにオブジェクト全体をコピーしてしまうからです。結果を事前に確保するか、ベクトル化された関数を使用すれば、この問題はほぼ解消されます。

列。データフレームは列のリストなので、各イテレーションでは1つの列全体が返されます。行を走査する必要がある場合は、seq_len(nrow(df)) を明示的に使用してください。

forループは、ハイパーパラメータのスイープ、交差検証のフォールド、およびトレーニングのエポックを制御します。これらのそれぞれには既知の反復回数があり、まさにfor構文はそのために設計されています。

はい。AIアシスタントは、ほとんどの要素ごとのループをベクトル化またはapply-family相当のループに変換できます。元のループを置き換える前に、両方のバージョンの出力をidentical()関数で比較してください。