404 Not Found

404 Not Found


nginx

Rの制御構造:if/for/while—条件文とループ

前回のレッスンでは演算子について学び、Rプログラムで「何かが真か偽かを判断する」ことができるようになりました。しかし、単に真偽を判定できるだけでは不十分です。プログラムには、タスクを繰り返し実行する(ループ)ことや、分岐処理を行う(条件分岐)ことも求められます。このレッスンでは、Rにおける「制御フロー」について学びます。具体的には、if/else条件分岐、for/whileループ、およびrepeat文について解説します。

Rにおける制御フローはPythonとは少し異なります。Rでは、コードブロックを{}で囲みます(インデントは使用しません)。また、if/else文全体が単一の式となります。このレッスンでは、これらの違いについて学びます。

1. 学習内容



2. データフィルタリングに関する話

(1) 課題:手作業による分類

シャオ・ジャオはデータアナリストです。上司から、100人の顧客を年齢別に分類するよう依頼されました。

Excelを使う場合、4つのネストしたIF関数を書く必要があります。Pythonを使う場合は、ループやif-else文を書く必要があります。しかし、Rにはベクトル専用に設計されたifelse()があり――

(2) Rを用いた解決策

R
# 5 The age of each customer
ages <- c(15, 22, 35, 50, 65)

# Done in one line of code 4 File Categories(Vectorization ifelse)
labels <- ifelse(ages < 18, "Minor",
          ifelse(ages < 31, "Youth",
            ifelse(ages < 51, "Middle Age", "Old Age")))

cat("Customer Segmentation:\n")
print(data.frame(Age = ages, Category = labels))

たった3行のコードで4クラス分類問題を解く。これがRの制御フローが持つ「ベクトル化」の利点であり、要するに、1つの文が1つの決定ベクトルとなるのです。



3. if/else:条件分岐

(1) if ステートメントの基本構文

R
# R uses { } to enclose a code block (Python uses indentation)
if (Conditions) {
  Execute when the condition is true
}
R
age <- 18

if (age >= 18) {
  cat("You're an adult now.\n")
}
# Output:You're an adult now.

(2) if-else:二者択一

R
if (Conditions) {
  Execute when the condition is true
} else {
  Execute when the condition is false
}
R
score <- 45

if (score >= 60) {
  cat("Passed!\n")
} else {
  cat("Fail,Need to take a makeup exam\n")
}
# Output:Fail,Need to take a makeup exam

(3) if-else if-else:多岐分岐

R
if (Conditions1) {
  Branch1
} else if (Conditions2) {
  Branch2
} else {
  Other
}
R
score <- 85

if (score >= 90) {
  cat("Excellent\n")
} else if (score >= 80) {
  cat("Good\n")
} else if (score >= 60) {
  cat("Passing Grade\n")
} else {
  cat("Fail\n")
}
# Output:Good

(4) RとPythonの主な違い

特集 R Python
コードブロック {} 中括弧 インデント(4スペース)
if 構文 if (x > 0) { ... } if x > 0:
全体としての表現 if/else が である場合(代入可能) if/else が である場合(代入不可)
三項演算 ifelse() 特殊関数 x if x > 0 else -x
R
# R Special Usage of:ifelse It is an expression
result <- if (score >= 60) "Passing Grade" else "Fail"
result
# [1] "Passing Grade"
⚠️ 注意:Rでは、if/else文を(単一の式として扱う場合)同じ行にelseを含める必要があります。2行に分けて記述すると、Rは構文エラーを報告します。



4. ifelse(): ベクトル化された意思決定

(1) なぜ ifelse() が必要なのでしょうか?

標準の if単一の値 しか評価できませんが、R では ベクトル全体 を評価する必要がある場合がよくあります。その場合は、ifelse() を使用してください:

100%
graph LR
    A["x = 1, 2, 3, 4, 5"] --> B["ifelse x > 3 yes no"]
    B --> C["no no no yes yes"]
    
    style A fill:#cce5ff
    style C fill:#d4edda
R
# Regular if It will throw an error(Only accept lengths 1)
x <- c(1, 2, 3, 4, 5)
if (x > 3) "L" else "S"   # Error: condition has length > 1

# Use ifelse() to resolve
ifelse(x > 3, "L", "S")
# [1] "S" "S" "S" "L" "L"

(2) ifelse() の構文

R
ifelse(Conditions, The value when the condition is true, Value when the condition is false)

(3) ネストされたifelse():多段階分類

R
ages <- c(15, 22, 35, 50, 65)

# 4 File Categories
labels <- ifelse(ages < 18, "Minor",
          ifelse(ages < 31, "Youth",
            ifelse(ages < 51, "Middle Age", "Old Age")))

print(data.frame(Age = ages, Category = labels))

出力:

R
  Age  Category
1   15 Minor
2   22   Youth
3   35   Middle Age
4   50   Middle Age
5   65   Old Age
💡 ヒント: ifelse() ネストが3階層以上ある場合は、よりわかりやすくするために dplyr::case_when()(第10課で解説)の使用をお勧めします。



5. forループ:要素を順に処理する

(1) 「for」ループの基本構文

R
for (Variable in Vector) {
  Code executed in each iteration
}

(2) ベクトルを反復処理する

R
# Iteration 1:5
for (i in 1:5) {
  cat("Iteration", i, "of the loop\n")
}
# Output:
# Iteration 1 of the loop
# Iteration 2 of the loop
# Iteration 3 of the loop
# Iteration 4 of the loop
# Iteration 5 of the loop

# Iterating Through a Character Vector
fruits <- c("Apple", "Banana", "Cherries")
for (fruit in fruits) {
  cat("I like to eat", fruit, "\n")
}

(3) 累積和(典型的な例)

R
# 1+2+3+...+100
total <- 0
for (i in 1:100) {
  total <- total + i
}
total
# [1] 5050

(4) ⚠️ Rはループ処理のパフォーマンスが低い

Rのforループは、Pythonのループに比べて10~100倍も遅い。Rでは、ループの代わりにベクトル化された演算の使用が推奨されている:

R
# Slow (Loop)
system.time({
  total <- 0
  for (i in 1:1e6) {
    total <- total + i
  }
})
# User  System  Passing 
# 0.40   0.00   0.40  ← 0.4 s

# Fast (Vectorization)
system.time({
  total <- sum(1:1e6)
})
# User  System  Passing 
# 0.01   0.00   0.01  <- 0.01 s (40x faster)
⚠️ 注意:Rでは「ベクトル化を優先する」ことが推奨されています。もしsum() mean() ifelse()を使って問題を解決できるなら、ループを書かないでください。



6. whileループ:条件付きループ

(1) while構文

R
while (Conditions) {
  Execute repeatedly when the condition is true
}

(2) 典型的な例:「数字当てゲーム」

R
# Target Number
target <- 42
guess <- 0
attempts <- 0

while (guess != target) {
  guess <- sample(1:100, 1)  # Guess at Random
  attempts <- attempts + 1
  if (attempts > 1000) break  # More than 1000 Second attempt
}
cat("Used", attempts, "Second guess\n")

(3) for との相違点

機能 対象 期間
目的 反復回数が既知のループ 反復回数が不明で、条件によってトリガーされるループ
終了 ベクトル走査の終了 条件不成立による終了
適用対象 データの反復処理 イベントの待機、ポーリング


7. repeatとbreak:無限ループ

(1) repeat 構文

R
repeat {
  Code
  if (Conditions) break  # Must have break,Otherwise, an infinite loop
}

(2) 実践編:メニューの選択

R
choice <- 0
repeat {
  cat("\n=== Main Menu ===\n")
  cat("1. Check the weather\n")
  cat("2. Look up stocks\n")
  cat("0. Exit\n")
  choice <- as.integer(readline("Please select:"))
  
  if (choice == 0) {
    cat("Goodbye!\n")
    break
  } else if (choice == 1) {
    cat("It's sunny today,25°C\n")
  } else if (choice == 2) {
    cat("Shanghai Stock Exchange 3000 pt\n")
  } else {
    cat("Invalid input\n")
  }
}
⚠️ 注意repeatbreak と組み合わせて使用する必要があります。そうしないと、無限ループが発生し(プログラムがフリーズします)、動作しなくなります。



8. next と break:ループ制御

キーワード 機能 シナリオ
next このラウンドをスキップして次のラウンドに進む 特定の項目をスキップする
break ループ全体を終了 対象が見つかり次第、直ちに終了
R
# next:Skip even numbers
for (i in 1:10) {
  if (i %% 2 == 0) next
  cat(i, " ")
}
# Output:1 3 5 7 9

cat("\n")

# break:Find the first one 7 Just log out
for (i in 1:10) {
  if (i == 7) break
  cat(i, " ")
}
# Output:1 2 3 4 5 6


9. よくある落とし穴

(1) 浮動小数点数の比較における落とし穴

R
# Seemingly equal,The actual values are not equal
0.1 + 0.2 == 0.3
# [1] FALSE  ← Actually, it is 0.30000000000000004

# The Correct Way to Do It:Comparison of Tolerances
abs(0.1 + 0.2 - 0.3) < 1e-9
# [1] TRUE

(2) else ステートメントは、新しい行、または同じ行に記述する必要があります

R
# ❌ Error:else Traveling Alone
if (TRUE) {
  cat("yes")
}
else {
  cat("no")
}
# Error: unexpected 'else' in "else"

# Correct: else must follow if block }
if (TRUE) {
  cat("yes")
} else {
  cat("no")
}
# Output:yes
💡 ヒント:解析上の曖昧さを避けるため、} else { を同じ行に記述してください。

(3) 自動的に出力されない場合

R
# In R, if has no "Automatic Printing" (Not like a function call)
if (TRUE) "yes"
# No output  ← Do not print

# Resolve: Use cat() or print() for explicit output
if (TRUE) cat("yes\n")
# Output:yes


10. 完全な例:顧客階層の管理

以下は、このレッスンで学んだすべての制御フローを結びつけた完全なワークフローの例です。

▶ サンプル:顧客セグメンテーションとマーケティング戦略

R
# ============================================
# Customer Segmentation and Marketing Strategies
# Features:By age+Classify Customers by Spending Amount
# ============================================

# 1. Preparation 6 Customer Data
customers <- data.frame(
  name = c("Alice", "Bob", "Charlie", "Diana", "Eve", "Frank"),
  age = c(15, 22, 35, 50, 65, 28),
  spend = c(100, 500, 2000, 5000, 10000, 800)
)

# 2. Use ifelse() Batch Grading (Vectorization)
customers$tier <- ifelse(customers$spend < 500, "Regular",
                  ifelse(customers$spend < 3000, "Silver Card",
                    ifelse(customers$spend < 8000, "Gold Card", "Diamond")))

# 3. Go through the customer list,Output Marketing Strategy(for Loop)
cat("=== Customer Segmentation and Marketing Strategies ===\n\n")
for (i in 1:nrow(customers)) {
  name <- customers$name[i]
  age <- customers$age[i]
  spend <- customers$spend[i]
  tier <- customers$tier[i]
  
  # Skip Diamond Members(Optimized)
  if (tier == "Diamond") {
    cat(name, "(", tier, "):", spend, "USD,Existing Customers,Priority Maintenance\n")
    next
  }
  
  # Exit Conditions(Demo break)
  if (spend > 5000) {
    cat(name, ": High-spending customers! Enter VIP Process\n")
  }
  
  # Age-Based Marketing Recommendations
  if (age < 18) {
    cat(name, "(", tier, "):Minor,Recommended Parent Card\n")
  } else if (age < 30) {
    cat(name, "(", tier, "):Youth,New Product Releases\n")
  } else if (age < 50) {
    cat(name, "(", tier, "):Middle Age,Promote Family Plans\n")
  } else {
    cat(name, "(", tier, "):Middle-Aged and Older Adults,Promote Health Products\n")
  }
}
▶ 試してみよう

期待される出力(抜粋):

R
=== Customer Segmentation and Marketing Strategies ===

Alice( Regular ):Minor,Recommended Parent Card
Bob( Regular ):Youth,New Product Releases
Charlie( Silver Card ):Middle Age,Promote Family Plans
Diana( Gold Card ):Middle Age,Promote Family Plans
Eve( Diamond ):10000 USD,Existing Customers,Priority Maintenance
Frank( Silver Card ):Youth,New Product Releases

❓ よくある質問

Q forループの処理が遅すぎる場合はどうすればよいですか?
A Rでは「まずベクトル化」が推奨されています。もしsum() mean() ifelse()を使って問題を解決できるなら、forループは書かないでください。RのループはPythonに比べて10~100倍遅いため、10万要素以上を扱う場合は慎重に使用してください。
Q forの代わりにwhileを使うべきなのはどのような場合ですか?
A 反復回数が不明な場合(例:イベントの待機、数字当てゲームなど)にはwhileを、反復回数が既知の場合(例:ベクトルに対する反復処理など)にはforを使用します。「早期終了可能な無限ループ」の場合は、repeatbreak を使用してください。

📖 まとめ


📝 練習問題

  1. 基本問題if/else if/else を使用して、以下の機能を実装する R スクリプトを作成してください。スコア score が与えられた場合、評価(90以上:優秀、80以上:良好、60以上:合格、それ以外:不合格)を出力します。95、75、60、40の4つの得点でスクリプトをテストし、出力のスクリーンショットを保存してください。

  2. 基本問題ifelse() を使用して、ベクトル c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) を奇数番目の要素と偶数番目の要素に分割し、その結果を出力してください。

  3. 基本問題for を使用して、ループ内で 5!(5 の階乗 = 5 × 4 × 3 × 2 × 1)を計算し、その過程と結果のスクリーンショットを保存してください。

  4. 応用演習:「数字当てゲーム」を作成してください:① sample(1:100, 1) を使用して、1 から 100 までの間の乱数を目標値として生成します。② while を使用して、ユーザーからの入力 (readline) を繰り返し処理します。③ 「高すぎます」または「低すぎます」というヒントを表示する;④ 数字が正しく当てられたら、「おめでとうございます!N回の試行で正解しました。」と出力する。プログラムを実行してテストしてください。

  5. 課題:1 から 100 までの整数を次のように処理するスクリプトを作成してください。① 3 の倍数(next)をスキップします。② 50に達したら終了する (break); ③ 残りの数の和を計算する。結果を確認する(1+2+4+5+7+8+...+49 = ? となるはず)。コードと出力のスクリーンショットを保存してください。

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%