数据挖掘与R语言

第5讲:流程控制语句——条件分支、循环、自定义函数

2026年09月15日

本讲导览

Control Flow & Functions

  • 一、复习导入 ——为什么需要“控制”代码的执行流程?
  • 二、条件分支 ——if/else,让代码会“判断”
  • 三、循环语句 ——for/while,让代码会“重复”
  • 四、自定义函数 ——function,把逻辑打包复用
  • 五、综合实战 ——把前几课代码封装成函数
  • 六、课堂总结与Exit Ticket ——编程解决重复劳动的三大武器

提示

今天的目标:判断(if/else)、重复(for/while)、封装(function)——这是编程解决“重复性劳动”的三大武器,缺一不可。

一、复习导入

为什么需要“控制”代码的执行流程?

1.1 复习提问

矩阵和列表最核心的区别是什么?(回顾第4课)

1.2 复习小测——选择题、填空题、代码题

选择题:下列哪个向量最终会被强制转换成字符型(character)?

A. c(1, 2, 3) B. c(TRUE, FALSE, 1) C. c(120, "135", 128) D. c(1L, 2L, 3L)

填空题:创建一个3行4列、按行填充的矩阵,写法为matrix(data, nrow = ___, byrow = ___)

代码题:数据框dfcompanyrevenue_2025两列,写一行代码筛选出revenue_2025大于1000的所有行。

1.3 复习小测参考答案

1.4 情境导入 —— 三个引导问题

回顾第2课的向量索引代码revenue[revenue>130]——这其实就是一种“条件判断”的体现。

如果想根据营收是否达标,分别打印“达标”或“未达标”的提示语,现在的知识能做到吗?——这就是“条件分支”要解决的问题

如果要给每个季度的营收都打印一句带序号的说明(如“第1季度营收为120万元”),向量化运算能一次搞定吗?不能,向量化运算适合“批量做同一件事”,但没法“逐个打印不同的话”——这就是“循环”要解决的问题

如果第1课的复利终值公式要在很多地方反复计算,每次都要重新敲一遍代码吗?——这就是“函数”要解决的问题

二、条件分支——if/else

让代码会“判断”

2.1 最简单的if语句

▶️ 查看代码
revenue <- 135
if (revenue > 130) {
  print("营收达标")
}
[1] "营收达标"

注记

条件表达式revenue > 130的结果是逻辑型(TRUE/FALSE),这正是第2课学的逻辑型数据类型的实际应用。

2.2 if...else

▶️ 查看代码
revenue <- 125
if (revenue > 130) {
  print("营收达标")
} else {
  print("营收未达标")
}
[1] "营收未达标"

2.3 多重条件——else if

▶️ 查看代码
revenue <- 135
if (revenue >= 150) {
  grade <- "A"
} else if (revenue >= 100) {
  grade <- "B"
} else {
  grade <- "C"
}
grade
[1] "B"

警告

else if的条件是按顺序依次判断的,一旦某个条件满足就不再继续往下判断——这是很多初学者容易忽略的执行顺序问题。

2.4 课堂练习

给定某季度营收revenue <- 95,用if/else判断并打印“营收达标”或“营收未达标”(阈值100万元);然后,调整营收的值(100以上)测试不同的结果。

▶️ 查看代码
revenue <- 95

if(revenue > 100){
  print("营收达标")
} else{
  print("营收未达标")
}
[1] "营收未达标"

三、循环语句——for/while

让代码会“重复”

3.1 for循环——已知重复次数

▶️ 查看代码
revenue <- c(120, 135, 128, 150)
for (i in 1:length(revenue)) {
  print(paste0("第", i, "季度营收为", revenue[i], "万元"))
}
[1] "第1季度营收为120万元"
[1] "第2季度营收为135万元"
[1] "第3季度营收为128万元"
[1] "第4季度营收为150万元"

注记

for循环里的1:length(revenue)正是第1课学过的数列生成知识的实际应用。这里用的是paste0()而不是paste()——paste()默认会在拼接的每一部分之间加一个空格,拼中文句子时通常不需要这个空格,paste0()(相当于paste(..., sep=""))更合适。

重要

如果只是想批量计算(如revenue*1.1),向量化运算1行代码就能搞定,不需要for循环;但如果想“逐个处理每个元素并做不同的事情”,就需要for循环——R语言里“能用向量化就不用循环”是一条重要的编程习惯。

3.2 for循环结合if —— 财务场景实战

▶️ 查看代码
for (i in 1:length(revenue)) {
  if (revenue[i] > 130) {
    print(paste0("第", i, "季度营收达标:", revenue[i]))
  } else {
    print(paste0("第", i, "季度营收未达标:", revenue[i]))
  }
}
[1] "第1季度营收未达标:120"
[1] "第2季度营收达标:135"
[1] "第3季度营收未达标:128"
[1] "第4季度营收达标:150"

3.3 while循环——简单了解

▶️ 查看代码
count <- 1
total <- 0
while (total < 500) {
  total <- total + revenue[count]
  count <- count + 1
}
print(paste0("累计", count-1, "个季度,总营收达到", total, "万元"))
[1] "累计4个季度,总营收达到533万元"

while循环适合“不知道要重复几次,直到满足某个条件才停止”的场景,财务分析中不算高频工具,此处了解即可

课堂练习(可穿插进行)

用for循环遍历company向量(贵州茅台、五粮液、泸州老窖),打印“公司X第一季度的营收是Y”

▶️ 查看代码
company <- c("贵州茅台", "五粮液", "泸州老窖")
revenue_Q1 <- c(120, 80, 200)

for (i in 1:length(revenue_Q1)) {
  print(paste0(company[i],"第一季度营收为", revenue_Q1[i], "万元"))
}
[1] "贵州茅台第一季度营收为120万元"
[1] "五粮液第一季度营收为80万元"
[1] "泸州老窖第一季度营收为200万元"

四、自定义函数——function

把重复的逻辑打包复用

4.1 为什么需要函数 —— 从复利计算说起

回顾第1课的复利终值代码:10000 * (1 + 0.05)^3

如果要计算10个不同本金、利率、年限的复利终值,要重复写10次这样的代码吗?

4.2 函数的基本结构

▶️ 查看代码
future_value <- function(principal, rate, years) {
  result <- principal * (1 + rate)^years
  return(result)
}
future_value(10000, 0.05, 3)
[1] 11576
▶️ 查看代码
future_value(20000, 0.04, 5)
[1] 24333

注记

function()括号里是参数(输入),大括号里是函数体(处理逻辑),return()返回值(输出)——这是函数的“三段论”。如果函数不写return(),R默认会返回函数体最后一行的值,但显式写出能让代码意图更清晰,建议初学阶段养成习惯。

4.3 函数与条件分支结合 —— 财务评级函数

▶️ 查看代码
rating_grade <- function(revenue) {
  if (revenue >= 150) {
    grade <- "A"
  } else if (revenue >= 100) {
    grade <- "B"
  } else {
    grade <- "C"
  }
  return(grade)
}
rating_grade(135)
[1] "B"
▶️ 查看代码
rating_grade(80)
[1] "C"

财务场景练习:把刚才写的if/else判断逻辑,改写成一个叫check_revenue()的函数,输入营收,返回“达标”或“未达标”(阀值可自由设定)

4.4 函数与向量 —— 一次搞定所有数据

▶️ 查看代码
revenue <- c(120, 135, 128, 150)
sapply(revenue, rating_grade)
[1] "B" "B" "B" "A"

sapply()可以把自定义函数应用到向量的每一个元素上,这是“函数+向量化”的强大组合(apply家族函数会在项目二、三系统学习,这里先“眼熟”)

五、综合实战

把前几课代码封装成函数

5.1 动手实战

  • 从第2课“向量常用函数”里选一段代码(如找出营收最高/最低季度),封装成一个函数revenue_summary(revenue),返回一句包含总营收、平均营收、最高季度的完整总结语句
▶️ 查看代码
# 定义营收总结函数
revenue_summary <- function(revenue) {
  total_rev <- sum(revenue)
  mean_rev <- mean(revenue)
  max_q <- which.max(revenue)
  max_val <- revenue[max_q]
  
  paste0(
    "全年总营收为 ", total_rev, 
    " 万元,平均季度营收为 ", round(mean_rev, 2), 
    " 万元,其中第 ", max_q, 
    " 季度表现最好,营收达到 ", max_val, " 万元。"
  )
}

# 示例数据
company_revenue <- c(120, 135, 128, 150)
cat(revenue_summary(company_revenue))
全年总营收为 533 万元,平均季度营收为 133.25 万元,其中第 4 季度表现最好,营收达到 150 万元。

5.2 课堂展示

现场邀请1-2名学生展示自己封装的函数与Quarto报告

六、课堂总结与Exit Ticket

编程解决重复劳动的三大武器

6.1 本讲知识回顾

▶️ 查看代码
flowchart LR
    A["条件分支<br/>if / else<br/>让代码会判断"] --> B["循环<br/>for / while<br/>让代码会重复"]
    B --> C["自定义函数<br/>function<br/>把逻辑打包复用"]

    style A fill:#1a3a5c,color:#fff
    style B fill:#2e5984,color:#fff
    style C fill:#7a4419,color:#fff

flowchart LR
    A["条件分支<br/>if / else<br/>让代码会判断"] --> B["循环<br/>for / while<br/>让代码会重复"]
    B --> C["自定义函数<br/>function<br/>把逻辑打包复用"]

    style A fill:#1a3a5c,color:#fff
    style B fill:#2e5984,color:#fff
    style C fill:#7a4419,color:#fff

条件分支(判断) → 循环(重复) → 函数(封装复用)——这是编程解决“重复性劳动”的三大武器

6.2 学习成果自查

对照一下,今天这五件事你都做到了吗?

  • ✓ 能够使用if/else完成条件判断
  • ✓ 能够使用for循环遍历向量并结合if进行条件处理
  • ✓ 能够编写简单的自定义函数(含参数、函数体、返回值)
  • ✓ 能够用sapply()将自定义函数应用到向量的每个元素
  • ✓ 能够将前几课的重复代码封装为可复用的函数

提示

如果有没打勾的,下课后一定要找同学或老师补上,不要留到下一讲。

6.3 Exit Ticket —— 写给自己的三个问题

请花1分钟,在纸条或在线问卷上简要回答:

  1. if/else和for循环分别解决什么问题?
  2. 自定义函数的三个组成部分是什么?
  3. 你觉得哪个知识点在实际财务工作中最有用?

课后作业

流程控制与函数综合练习

建议使用Quarto(.qmd)完成,保留代码与结果:

  1. 用if/else编写代码:给定某产品的月销售额,判断并打印“畅销”(大于等于100万元)、“一般”(50-100万元)、“滞销”(小于50万元)三档评价

  2. 用for循环遍历一个包含6个月销售额的向量,逐月打印“第X月销售额为Y万元,评价为Z”(结合第(1)题的判断逻辑)

  3. 将第(1)题的判断逻辑封装成一个函数sales_level(x),并完成:

    • 分别用几个不同的数值测试函数是否正常工作
    • sapply()将函数应用到第(2)题的销售额向量上,一次得到所有月份的评价结果
  4. 【选做】封装一个函数,输入本金、利率、年限,返回“本金X元,年利率Y,Z年后本息合计为W元”的完整语句(提示:结合第1课的复利终值公式与paste0()

下讲预告

第6讲:数据管理基础——排序、合并、分组统计

提示

课前准备:继续用Quarto整理作业,把今天写的自定义函数保存好,下节课整理数据时可能会用到。

谢谢!

第5讲:流程控制语句——条件分支、循环、自定义函数

"In God we trust; all others must bring data." — W. Edwards Deming,质量管理与统计学家

朱 奇 | 锦城大学 · 财会学院