未记录事实核验 · 状态:维护中

记录仅说明核验时间与维护状态,不保证适用于所有环境;使用前请留意正文中的版本、适用条件与风险提示。

warning 适用边界与维护说明

本文适合已有R数据框、函数和基础统计知识的读者练习综合dplyr流水线;管道入门中的data及最佳实践模板中的列名、条件为占位内容,使用时须按实际数据替换并确保后续所需列未被select()移除。学生数据、画像和教学建议仅展示模拟分析与规则生成,开头人物、规模和耗时也不是性能测试依据。百分位阈值不等于严格按人数取前50%,单人组结果已显式处理;slice_max默认保留并列,手工第三名阈值要求至少3行。当前正文的“优秀率”在基础示例中使用90分、综合案例的部分统计中使用85分,比较时须区分口径;“主要问题”未单独识别体育不及格,不能作为完整的学生问题诊断。本次仅作结构审阅,未运行代码或进行外部事实核验。

🔧 dplyr数据操作 - 数据处理的瑞士军刀

tip 💝 给数据新手的贴心话

🤗 学会dplyr,就像获得了数据处理的"超能力"!

如果你现在想着:

  • "数据这么乱,怎么整理啊?"
  • "Excel里要点很多下,R里会不会更复杂?"
  • "这么多函数记得住吗?"

别担心! dplyr的设计哲学就是让复杂的数据操作变简单 ✨

🔧 想象dplyr是一套完美的工具箱

就像装修房子需要不同工具:

  • 🔨 select() = 锤子(选择需要的列)
  • ✂️ filter() = 剪刀(筛选需要的行)
  • 📏 arrange() = 尺子(数据排序整齐)
  • 🔧 mutate() = 扳手(创建新的列)
  • 📊 summarise() = 计算器(统计汇总)
  • 🗂️ group_by() = 分类盒(数据分组)

每个工具都简单易用,组合起来就能解决复杂问题! 🌟

假设数据分析师小赵拿到一个包含50万行销售数据的表格,需要按地区分组、筛选高价值客户、计算月度增长率、排序输出报告。若手工处理预计需要2小时,可尝试用dplyr流水线组织这些步骤;这里的人物、耗时和任务规模仅为情境假设,并非真实经历或性能测试。实际代码量、耗时和错误风险取决于数据结构、业务口径、硬件与操作方式。

🌟 dplyr的核心优势

%%{init: {"theme":"base","themeVariables":{"fontFamily":"PingFang SC, -apple-system, Source Han Serif SC, serif","fontSize":"16px","background":"#FDFBF5","primaryColor":"#FDFBF5","primaryTextColor":"#2D2A26","primaryBorderColor":"#6E6A60","secondaryColor":"#E8EFE8","secondaryBorderColor":"#8FA890","secondaryTextColor":"#2D2A26","tertiaryColor":"#FDFBF5","tertiaryBorderColor":"#9A9488","tertiaryTextColor":"#6E6A60","lineColor":"#6E6A60","textColor":"#2D2A26","mainBkg":"#FDFBF5","nodeBorder":"#2D5A3D","clusterBkg":"#F3EEDF","clusterBorder":"#9A9488","edgeLabelBackground":"#FDFBF5"},"flowchart":{"htmlLabels":true,"curve":"basis","padding":20,"nodeSpacing":60,"rankSpacing":70,"useMaxWidth":false},"themeCSS":".node rect, .node polygon, .node circle { stroke-width: 1.5px; } .edgePath .path { stroke-width: 1.5px; } .cluster-label .nodeLabel, .cluster-label foreignObject { color: #2D2A26 !important; } .edgeLabel, .edgeLabel foreignObject { color: #2D2A26 !important; background-color: #FDFBF5; } .edgeLabel rect { fill: #FDFBF5; }"}}%%
flowchart TD
    A[dplyr核心优势]
    B[🔗 管道操作<br/>思路连贯]
    A --> B
    A --> C[📝 语法直观<br/>接近自然语言]
    C --> D[⚡ 执行高效<br/>C++优化]
    A --> D
    A --> E[🔧 功能丰富<br/>支持常见数据操作]
    E --> F[🎯 专注数据<br/>一个包搞定]
    A --> F
    style A fill:#e1f5fe
    style B fill:#f3e5f5
    style C fill:#fff3e0
    style D fill:#e8f5e8
    style E fill:#fce4ec
    style F fill:#f9fbe7

🛠️ dplyr六大核心函数

📋 函数概览

# 安装和加载dplyr
# install.packages("tidyverse")  # 包含dplyr
# 如未安装,请先执行:
# install.packages(c("dplyr", "stringr", "tidyr", "moments", "scales"))
library(dplyr)
library(stringr)
library(tidyr)
# moments和scales在下文通过包名::函数名调用

# 六大核心函数一览
# select()   - 选择列(选择变量)
# filter()   - 筛选行(筛选观测)
# arrange()  - 排序(重新排列)
# mutate()   - 创建新列(变换数据)
# summarise() - 汇总统计(summarize的英式拼写)
# group_by() - 分组操作(分组分析)

🎯 管道操作符 %>%

info 🔗 **管道操作的魔力**

管道操作符 %>% 就像流水线:

传统方式(嵌套地狱):

result <- summarise(
  arrange(
    filter(
      select(data, 姓名, 年龄, 成绩),
      成绩 > 80
    ),
    成绩
  ),
  平均分 = mean(成绩)
)

管道方式(清晰流畅):

result <- data %>%
  select(姓名, 年龄, 成绩) %>%
  filter(成绩 > 80) %>%
  arrange(成绩) %>%
  summarise(平均分 = mean(成绩))

读起来就像:"拿数据 → 选择列 → 筛选行 → 排序 → 汇总"

🔍 select() - 选择你需要的列

🎯 基础列选择

# 创建示例数据
students <- data.frame(
  学号 = sprintf("2024%03d", 1:10),
  姓名 = paste0("学生", 1:10),
  性别 = sample(c("男", "女"), 10, replace = TRUE),
  年龄 = sample(18:22, 10, replace = TRUE),
  专业 = sample(c("计算机", "数学", "物理"), 10, replace = TRUE),
  数学成绩 = round(rnorm(10, 85, 10), 1),
  英语成绩 = round(rnorm(10, 80, 12), 1),
  编程成绩 = round(rnorm(10, 88, 8), 1),
  stringsAsFactors = FALSE
)

print(students)

# 1. 按名称选择列
basic_info <- students %>%
  select(姓名, 年龄, 专业)

print(basic_info)

# 2. 按位置选择列
first_three <- students %>%
  select(1:3)  # 选择前3列

# 3. 排除不需要的列
without_id <- students %>%
  select(-学号)  # 排除学号列

without_multiple <- students %>%
  select(-c(学号, 年龄))  # 排除多列

# 4. 按模式选择列
# 选择包含"成绩"的列
scores_only <- students %>%
  select(contains("成绩"))

# 选择以某字符开头的列
student_info <- students %>%
  select(starts_with("姓"))

# 选择以某字符结尾的列
personal_info <- students %>%
  select(ends_with("龄"))

print(scores_only)

🔧 高级选择技巧

# 1. 重命名同时选择
renamed_data <- students %>%
  select(
    ID = 学号,
    Name = 姓名,
    Age = 年龄,
    Math = 数学成绩
  )

# 2. 重新排列列顺序
reordered <- students %>%
  select(姓名, 专业, everything())  # everything()表示其他所有列

# 3. 根据数据类型选择
numeric_cols <- students %>%
  select(where(is.numeric))  # 选择所有数值列

character_cols <- students %>%
  select(where(is.character))  # 选择所有字符列

print(numeric_cols)

# 4. 条件选择
high_variance_cols <- students %>%
  select(where(~ is.numeric(.x) && var(.x, na.rm = TRUE) > 50))

# 5. 使用变量选择列
score_columns <- c("数学成绩", "英语成绩", "编程成绩")
selected_scores <- students %>%
  select(all_of(score_columns))

🔍 filter() - 精确筛选数据行

🎯 基础行筛选

# 1. 单条件筛选
# 筛选年龄大于20的学生
older_students <- students %>%
  filter(年龄 > 20)

# 筛选计算机专业的学生
cs_students <- students %>%
  filter(专业 == "计算机")

# 筛选数学成绩优秀的学生
excellent_math <- students %>%
  filter(数学成绩 >= 90)

print(excellent_math)

# 2. 多条件筛选(AND逻辑)
# 筛选年龄>20且专业是计算机的学生
cs_older <- students %>%
  filter(年龄 > 20, 专业 == "计算机")

# 等价写法
cs_older2 <- students %>%
  filter(年龄 > 20 & 专业 == "计算机")

# 3. 或逻辑筛选(OR逻辑)
# 筛选专业是计算机或数学的学生
stem_students <- students %>%
  filter(专业 == "计算机" | 专业 == "数学")

# 使用%in%操作符(更简洁)
stem_students2 <- students %>%
  filter(专业 %in% c("计算机", "数学"))

print(stem_students2)

# 4. 数值范围筛选
# 筛选年龄在19-21之间的学生
age_range <- students %>%
  filter(年龄 >= 19, 年龄 <= 21)

# 等价写法
age_range2 <- students %>%
  filter(between(年龄, 19, 21))

print(age_range2)

🔧 高级筛选技巧

# 1. 字符串模糊匹配
# 筛选姓名包含"1"的学生
name_contains <- students %>%
  filter(str_detect(姓名, "1"))

# 2. 多列条件筛选
# 筛选任意一科成绩>90的学生
high_achievers <- students %>%
  filter(数学成绩 > 90 | 英语成绩 > 90 | 编程成绩 > 90)

# 3. 筛选前N名
# 按数学成绩筛选前3名:以下第三名阈值写法要求至少有3行数据
# 阈值写法及slice_max默认均保留并列,因此结果可能超过3人
# 如需最多3人,可使用slice_max(数学成绩, n = 3, with_ties = FALSE),并明确并列取舍规则
top_math <- students %>%
  filter(数学成绩 >= sort(数学成绩, decreasing = TRUE)[3])

# 使用slice_max更简单
top_math2 <- students %>%
  slice_max(数学成绩, n = 3)

print(top_math2)

# 4. 筛选缺失值
# 假设有缺失值的数据
students_with_na <- students
students_with_na$数学成绩[c(1,3)] <- NA

# 筛选非缺失值
complete_math <- students_with_na %>%
  filter(!is.na(数学成绩))

# 筛选缺失值
missing_math <- students_with_na %>%
  filter(is.na(数学成绩))

# 5. 复杂条件筛选
# 筛选综合表现优秀的学生(平均分>85且没有科目<70)
excellent_overall <- students %>%
  rowwise() %>%
  mutate(平均分 = mean(c(数学成绩, 英语成绩, 编程成绩))) %>%
  filter(
    平均分 > 85,
    数学成绩 >= 70,
    英语成绩 >= 70,
    编程成绩 >= 70
  ) %>%
  ungroup()

print(excellent_overall)

📊 arrange() - 让数据井然有序

🎯 基础排序

# 1. 单列排序
# 按年龄升序排列
age_asc <- students %>%
  arrange(年龄)

# 按数学成绩降序排列
math_desc <- students %>%
  arrange(desc(数学成绩))

print(math_desc)

# 2. 多列排序
# 先按专业,再按数学成绩降序
multi_sort <- students %>%
  arrange(专业, desc(数学成绩))

print(multi_sort)

# 3. 字符串排序
# 按姓名字母顺序排列
name_sort <- students %>%
  arrange(姓名)

print(name_sort)

🔧 高级排序技巧

# 1. 自定义排序顺序
# 按专业自定义顺序排列
custom_order <- students %>%
  mutate(专业_顺序 = factor(专业, levels = c("计算机", "数学", "物理"))) %>%
  arrange(专业_顺序) %>%
  select(-专业_顺序)

print(custom_order)

# 2. 按计算列排序
# 按总分排序
total_score_sort <- students %>%
  mutate(总分 = 数学成绩 + 英语成绩 + 编程成绩) %>%
  arrange(desc(总分))

print(total_score_sort)

# 3. 随机排序
# 随机打乱顺序
random_order <- students %>%
  slice_sample(n = nrow(students))

# 4. 条件排序
# 女生按数学成绩排序,男生按英语成绩排序
conditional_sort <- students %>%
  arrange(性别, ifelse(性别 == "女", desc(数学成绩), desc(英语成绩)))

🔧 mutate() - 创造新的数据列

🎯 基础列创建

# 1. 创建简单计算列
enhanced_students <- students %>%
  mutate(
    总分 = 数学成绩 + 英语成绩 + 编程成绩,
    平均分 = 总分 / 3,
    平均分_四舍五入 = round(平均分, 1)
  )

print(enhanced_students)

# 2. 创建条件列
graded_students <- students %>%
  mutate(
    数学等级 = case_when(
      数学成绩 >= 90 ~ "优秀",
      数学成绩 >= 80 ~ "良好",
      数学成绩 >= 70 ~ "中等",
      数学成绩 >= 60 ~ "及格",
      TRUE ~ "不及格"
    ),
    是否成年 = ifelse(年龄 >= 18, "是", "否"),
    性别编码 = if_else(性别 == "男", 1, 0)
  )

print(graded_students)

# 3. 基于多列创建新列
analysis_students <- students %>%
  mutate(
    总分 = 数学成绩 + 英语成绩 + 编程成绩,
    最高分科目 = case_when(
      数学成绩 >= 英语成绩 & 数学成绩 >= 编程成绩 ~ "数学",
      英语成绩 >= 数学成绩 & 英语成绩 >= 编程成绩 ~ "英语",
      TRUE ~ "编程"
    ),
    是否偏科 = abs(数学成绩 - 英语成绩) > 15 | 
              abs(数学成绩 - 编程成绩) > 15 | 
              abs(英语成绩 - 编程成绩) > 15
  )

print(analysis_students)

🔧 高级列操作

# 1. 窗口函数
ranked_students <- students %>%
  mutate(
    数学排名 = rank(desc(数学成绩)),
    数学百分位 = percent_rank(数学成绩),
    累计平均 = cummean(数学成绩),
    与平均分差 = 数学成绩 - mean(数学成绩)
  )

print(ranked_students)

# 2. 字符串处理
string_processed <- students %>%
  mutate(
    姓名_大写 = toupper(姓名),
    学号_后三位 = str_sub(学号, -3, -1),
    专业_简称 = case_when(
      专业 == "计算机" ~ "CS",
      专业 == "数学" ~ "MATH",
      专业 == "物理" ~ "PHYS",
      TRUE ~ 专业
    )
  )

# 3. 跨行计算
cross_row_calc <- students %>%
  arrange(数学成绩) %>%
  mutate(
    前一名成绩 = lag(数学成绩),
    后一名成绩 = lead(数学成绩),
    与前一名差距 = 数学成绩 - lag(数学成绩),
    与前行成绩比较 = case_when(
      is.na(lag(数学成绩)) ~ "起始行(最低分)",
      数学成绩 > lag(数学成绩) ~ "高于前行",
      数学成绩 == lag(数学成绩) ~ "与前行相同",
      TRUE ~ "低于前行"
    )
  )

print(cross_row_calc)

# 4. 批量创建列
# 为所有成绩列创建等级
score_grades <- students %>%
  mutate(
    across(
      contains("成绩"),
      ~ case_when(
        .x >= 90 ~ "A",
        .x >= 80 ~ "B", 
        .x >= 70 ~ "C",
        .x >= 60 ~ "D",
        TRUE ~ "F"
      ),
      .names = "{.col}_等级"
    )
  )

print(score_grades)

📊 summarise() - 数据汇总统计

🎯 基础汇总统计

# 1. 简单汇总
basic_summary <- students %>%
  summarise(
    学生总数 = n(),
    平均年龄 = mean(年龄),
    数学平均分 = mean(数学成绩),
    数学最高分 = max(数学成绩),
    数学最低分 = min(数学成绩),
    数学标准差 = sd(数学成绩)
  )

print(basic_summary)

# 2. 多列汇总
multi_summary <- students %>%
  summarise(
    across(
      contains("成绩"),
      list(
        平均 = ~ mean(.x, na.rm = TRUE),
        最大 = ~ max(.x, na.rm = TRUE),
        最小 = ~ min(.x, na.rm = TRUE),
        标准差 = ~ sd(.x, na.rm = TRUE)
      ),
      .names = "{.col}_{.fn}"
    )
  )

print(multi_summary)

# 3. 自定义统计函数
custom_summary <- students %>%
  summarise(
    总人数 = n(),
    男生人数 = sum(性别 == "男"),
    女生人数 = sum(性别 == "女"),
    成年人比例 = mean(年龄 >= 18),
    数学优秀率 = mean(数学成绩 >= 90),
    数学及格率 = mean(数学成绩 >= 60),
    全科及格人数 = sum(数学成绩 >= 60 & 英语成绩 >= 60 & 编程成绩 >= 60)
  )

print(custom_summary)

🔧 高级汇总技巧

# 1. 条件汇总
conditional_summary <- students %>%
  summarise(
 # 不同性别的统计
    男生平均年龄 = mean(年龄[性别 == "男"]),
    女生平均年龄 = mean(年龄[性别 == "女"]),
    
 # 不同专业的统计
    计算机专业人数 = sum(专业 == "计算机"),
    数学专业平均分 = mean(数学成绩[专业 == "数学"]),
    
 # 成绩分段统计
    优秀学生数 = sum(数学成绩 >= 90),
    中等学生数 = sum(数学成绩 >= 70 & 数学成绩 < 90),
    需要帮助学生数 = sum(数学成绩 < 70)
  )

print(conditional_summary)

# 2. 百分位数和分位数
quantile_summary <- students %>%
  summarise(
    数学成绩_25分位 = quantile(数学成绩, 0.25),
    数学成绩_中位数 = median(数学成绩),
    数学成绩_75分位 = quantile(数学成绩, 0.75),
    数学成绩_四分位距 = IQR(数学成绩)
  )

print(quantile_summary)

# 3. 自定义复杂统计
complex_summary <- students %>%
  summarise(
 # 基础统计
    样本大小 = n(),
    
 # 集中趋势
    数学平均分 = mean(数学成绩),
    数学中位数 = median(数学成绩),
    
 # 离散程度
    数学方差 = var(数学成绩),
    数学变异系数 = sd(数学成绩) / mean(数学成绩),
    
 # 分布形状
    数学偏度 = moments::skewness(数学成绩),
    数学峰度 = moments::kurtosis(数学成绩),
    
 # 实用统计
    优秀率 = scales::percent(mean(数学成绩 >= 90)),
    及格率 = scales::percent(mean(数学成绩 >= 60)),
    
 # 置信区间
    平均分下限 = t.test(数学成绩)$conf.int[1],
    平均分上限 = t.test(数学成绩)$conf.int[2]
  )

print(complex_summary)

🗂️ group_by() - 分组分析的威力

🎯 基础分组操作

# 1. 按单个变量分组
by_gender <- students %>%
  group_by(性别) %>%
  summarise(
    人数 = n(),
    平均年龄 = mean(年龄),
    数学平均分 = mean(数学成绩),
    英语平均分 = mean(英语成绩),
    .groups = "drop"  # 取消分组
  )

print(by_gender)

# 2. 按多个变量分组
by_gender_major <- students %>%
  group_by(性别, 专业) %>%
  summarise(
    人数 = n(),
    数学平均分 = round(mean(数学成绩), 2),
    英语平均分 = round(mean(英语成绩), 2),
    .groups = "drop"
  )

print(by_gender_major)

# 3. 分组后的其他操作
# 分组排序
grouped_arrange <- students %>%
  group_by(专业) %>%
  arrange(专业, desc(数学成绩))

print(grouped_arrange)

# 分组筛选
top_by_major <- students %>%
  group_by(专业) %>%
  slice_max(数学成绩, n = 1) %>%
  ungroup()

print(top_by_major)

🔧 高级分组分析

# 1. 分组窗口函数
windowed_analysis <- students %>%
  group_by(专业) %>%
  mutate(
    专业内排名 = rank(desc(数学成绩)),
    专业平均分 = mean(数学成绩),
    与专业平均差 = 数学成绩 - mean(数学成绩),
    专业内百分位 = percent_rank(数学成绩),
    # 按百分位阈值筛选,不保证人数恰为专业人数的50%;并列会影响入选比例
    # 单人组的percent_rank结果为NaN,此处显式标为NA
    是否达到专业百分位阈值 = if_else(
      is.na(专业内百分位), NA, 专业内百分位 >= 0.5
    )
  ) %>%
  ungroup()

print(windowed_analysis)

# 2. 复杂分组统计
comprehensive_analysis <- students %>%
  group_by(专业, 性别) %>%
  summarise(
 # 基础统计
    人数 = n(),
    
 # 数学成绩分析
    数学平均分 = round(mean(数学成绩), 2),
    数学中位数 = median(数学成绩),
    数学标准差 = round(sd(数学成绩), 2),
    数学最高分 = max(数学成绩),
    数学最低分 = min(数学成绩),
    
 # 英语成绩分析
    英语平均分 = round(mean(英语成绩), 2),
    英语优秀率 = round(mean(英语成绩 >= 90) * 100, 1),
    
 # 综合分析
    全科及格率 = round(mean(数学成绩 >= 60 & 英语成绩 >= 60 & 编程成绩 >= 60) * 100, 1),
    
    .groups = "drop"
  ) %>%
  arrange(专业, desc(人数))

print(comprehensive_analysis)

# 3. 分组条件操作
conditional_group_ops <- students %>%
  group_by(专业) %>%
  mutate(
    专业人数 = n(),
    专业标签 = case_when(
      专业人数 >= 4 ~ "大专业",
      专业人数 >= 2 ~ "中专业", 
      TRUE ~ "小专业"
    ),
    在专业中表现 = case_when(
      数学成绩 >= quantile(数学成绩, 0.75) ~ "优秀",
      数学成绩 >= quantile(数学成绩, 0.5) ~ "良好",
      数学成绩 >= quantile(数学成绩, 0.25) ~ "一般",
      TRUE ~ "需要帮助"
    )
  ) %>%
  ungroup()

print(conditional_group_ops)

🎯 dplyr实战案例:学生成绩全面分析

# =====================================
# 案例:学生成绩管理系统完整分析
# =====================================

cat("🎓 学生成绩管理系统 - dplyr实战\n")
cat("=====================================\n")

# 创建更大的示例数据集
set.seed(123)
large_students <- data.frame(
  学号 = sprintf("2024%04d", 1:100),
  姓名 = paste0("学生", 1:100),
  班级 = rep(c("计算机1班", "计算机2班", "数学1班", "数学2班", "物理1班"), each = 20),
  性别 = sample(c("男", "女"), 100, replace = TRUE, prob = c(0.6, 0.4)),
  年龄 = sample(18:23, 100, replace = TRUE),
  入学成绩 = round(rnorm(100, 580, 50), 0),
  数学成绩 = round(rnorm(100, 85, 12), 1),
  英语成绩 = round(rnorm(100, 78, 15), 1),
  编程成绩 = round(rnorm(100, 82, 10), 1),
  体育成绩 = round(rnorm(100, 80, 8), 1),
  stringsAsFactors = FALSE
)

cat("📊 数据概览:", nrow(large_students), "名学生,", ncol(large_students), "个变量\n\n")

# 1. 数据清洗和预处理
cat("🧹 数据清洗和预处理...\n")
cleaned_students <- large_students %>%
 # 确保成绩在合理范围内
  mutate(
    across(c(数学成绩, 英语成绩, 编程成绩, 体育成绩), ~ pmax(0, pmin(100, .x))),
    专业 = str_extract(班级, "^[^0-9]+"),
    班级号 = str_extract(班级, "[0-9]+班$")
  ) %>%
 # 计算综合指标
  mutate(
    总分 = 数学成绩 + 英语成绩 + 编程成绩 + 体育成绩,
    平均分 = 总分 / 4,
    主科平均 = (数学成绩 + 英语成绩 + 编程成绩) / 3,
    是否优秀 = 平均分 >= 85,
    是否全科及格 = 数学成绩 >= 60 & 英语成绩 >= 60 & 编程成绩 >= 60 & 体育成绩 >= 60
  )

cat("✅ 数据清洗完成\n\n")

# 2. 整体情况分析
cat("📈 整体情况分析\n")
cat("=====================================\n")

overall_stats <- cleaned_students %>%
  summarise(
    学生总数 = n(),
    男生数量 = sum(性别 == "男"),
    女生数量 = sum(性别 == "女"),
    平均年龄 = round(mean(年龄), 2),
    
    总分平均 = round(mean(总分), 2),
    总分标准差 = round(sd(总分), 2),
    
    优秀学生数 = sum(是否优秀),
    优秀率 = paste0(round(mean(是否优秀) * 100, 1), "%"),
    
    全科及格数 = sum(是否全科及格),
    全科及格率 = paste0(round(mean(是否全科及格) * 100, 1), "%")
  )

print(overall_stats)

# 3. 专业对比分析
cat("\n📊 专业对比分析\n")
cat("=====================================\n")

major_comparison <- cleaned_students %>%
  group_by(专业) %>%
  summarise(
    学生数 = n(),
    男女比例 = paste0(sum(性别=="男"), ":", sum(性别=="女")),
    
    平均分_均值 = round(mean(平均分), 2),
    平均分_中位数 = round(median(平均分), 2),
    
    数学均分 = round(mean(数学成绩), 2),
    英语均分 = round(mean(英语成绩), 2),
    编程均分 = round(mean(编程成绩), 2),
    
    优秀率 = paste0(round(mean(是否优秀) * 100, 1), "%"),
    全科及格率 = paste0(round(mean(是否全科及格) * 100, 1), "%"),
    
    .groups = "drop"
  ) %>%
  arrange(desc(平均分_均值))

print(major_comparison)

# 4. 班级详细分析
cat("\n🏫 班级详细分析\n")
cat("=====================================\n")

class_analysis <- cleaned_students %>%
  group_by(班级) %>%
  summarise(
    人数 = n(),
    
 # 各科平均分
    数学均分 = round(mean(数学成绩), 1),
    英语均分 = round(mean(英语成绩), 1), 
    编程均分 = round(mean(编程成绩), 1),
    体育均分 = round(mean(体育成绩), 1),
    
 # 综合指标
    总平均分 = round(mean(平均分), 1),
    优秀人数 = sum(是否优秀),
    
 # 各科及格率
    数学及格率 = paste0(round(mean(数学成绩 >= 60) * 100, 1), "%"),
    英语及格率 = paste0(round(mean(英语成绩 >= 60) * 100, 1), "%"),
    
    .groups = "drop"
  ) %>%
  arrange(desc(总平均分))

print(class_analysis)

# 5. 性别差异分析
cat("\n👥 性别差异分析\n")
cat("=====================================\n")

gender_analysis <- cleaned_students %>%
  group_by(性别) %>%
  summarise(
    人数 = n(),
    平均年龄 = round(mean(年龄), 2),
    
 # 各科成绩对比
    数学平均 = round(mean(数学成绩), 2),
    英语平均 = round(mean(英语成绩), 2),
    编程平均 = round(mean(编程成绩), 2),
    体育平均 = round(mean(体育成绩), 2),
    
 # 优秀率对比
    总分优秀率 = paste0(round(mean(是否优秀) * 100, 1), "%"),
    
 # 各科优秀率
    数学优秀率 = paste0(round(mean(数学成绩 >= 85) * 100, 1), "%"),
    英语优秀率 = paste0(round(mean(英语成绩 >= 85) * 100, 1), "%"),
    
    .groups = "drop"
  )

print(gender_analysis)

# 6. 优秀学生画像
cat("\n🌟 优秀学生画像分析\n")
cat("=====================================\n")

excellent_students <- cleaned_students %>%
  filter(是否优秀) %>%
  select(学号, 姓名, 班级, 性别, 年龄, 数学成绩, 英语成绩, 编程成绩, 平均分) %>%
  arrange(desc(平均分))

cat("🏆 优秀学生top10:\n")
print(head(excellent_students, 10))

# 优秀学生特征分析
excellent_profile <- cleaned_students %>%
  filter(是否优秀) %>%
  summarise(
    优秀学生数 = n(),
    平均年龄 = round(mean(年龄), 2),
    男生比例 = paste0(round(mean(性别 == "男") * 100, 1), "%"),
    
    数学均分 = round(mean(数学成绩), 2),
    英语均分 = round(mean(英语成绩), 2),
    编程均分 = round(mean(编程成绩), 2),
    
    入学成绩均值 = round(mean(入学成绩), 2)
  )

cat("\n📋 优秀学生群体特征:\n")
print(excellent_profile)

# 7. 需要关注的学生
cat("\n⚠️ 需要关注的学生\n")
cat("=====================================\n")

attention_students <- cleaned_students %>%
  filter(!是否全科及格 | 平均分 < 70) %>%
  select(学号, 姓名, 班级, 数学成绩, 英语成绩, 编程成绩, 体育成绩, 平均分) %>%
  mutate(
    主要问题 = case_when(
      数学成绩 < 60 & 英语成绩 < 60 ~ "数学英语双弱",
      数学成绩 < 60 ~ "数学偏弱", 
      英语成绩 < 60 ~ "英语偏弱",
      编程成绩 < 60 ~ "编程偏弱",
      TRUE ~ "整体偏弱"
    )
  ) %>%
  arrange(平均分)

cat("需要重点关注的学生数量:", nrow(attention_students), "\n")
if(nrow(attention_students) > 0) {
  cat("前5名需要帮助的学生:\n")
  print(head(attention_students, 5))
}

# 8. 生成改进建议
cat("\n💡 改进建议\n")
cat("=====================================\n")

# 班级层面建议
class_suggestions <- cleaned_students %>%
  group_by(班级) %>%
  summarise(
    平均分 = mean(平均分),
    及格率 = mean(是否全科及格),
    数学弱势人数 = sum(数学成绩 < 70),
    英语弱势人数 = sum(英语成绩 < 70),
    .groups = "drop"
  ) %>%
  mutate(
    建议 = case_when(
      平均分 < 75 ~ "整体加强基础教学",
      数学弱势人数 >= 3 ~ "重点加强数学辅导",
      英语弱势人数 >= 3 ~ "重点加强英语辅导",
      及格率 < 0.9 ~ "关注后进生帮扶",
      TRUE ~ "保持当前教学水平"
    )
  )

print(class_suggestions)

cat("\n✅ 分析完成!关键发现:\n")
cat(sprintf("- 全校优秀率:%.1f%%\n", mean(cleaned_students$是否优秀) * 100))
cat(sprintf("- 全科及格率:%.1f%%\n", mean(cleaned_students$是否全科及格) * 100))
cat(sprintf("- 需要重点关注学生:%d人\n", nrow(attention_students)))

best_class <- class_analysis$班级[1]
cat(sprintf("- 表现最好班级:%s (平均分%.1f)\n", best_class, class_analysis$总平均分[1]))

🎉 dplyr数据操作技能达成!

success 🌟 **恭喜你!现在你已经掌握了**

  • ✅ select()技能:自如选择需要的数据列
  • ✅ filter()技能:精确筛选符合条件的数据行
  • ✅ arrange()技能:让数据按需排序井然有序
  • ✅ mutate()技能:创建计算列扩展数据维度
  • ✅ summarise()技能:汇总统计洞察数据规律
  • ✅ group_by()技能:分组分析发现深层见解
  • ✅ 管道操作:流畅串联复杂数据处理流程

你已经拥有了数据处理的"超级工具箱"! 🚀

🎯 dplyr最佳实践总结

# =====================================
# dplyr最佳实践速查手册
# =====================================

# 1. 基础操作模板
data_processing_template <- function(data) {
  result <- data %>%
 # 数据清洗
    filter(!is.na(关键列)) %>%
 # 选择需要的列
    select(contains("重要"), starts_with("前缀")) %>%
 # 创建新的计算列
    mutate(
      新列 = 列1 + 列2,
      分类 = case_when(
        条件1 ~ "类别1",
        条件2 ~ "类别2", 
        TRUE ~ "其他"
      )
    ) %>%
 # 排序
    arrange(desc(重要列)) %>%
 # 分组分析
    group_by(分组列) %>%
    summarise(
      计数 = n(),
      平均值 = mean(数值列),
      .groups = "drop"
    )
  
  return(result)
}

# 2. 常用函数组合
useful_combinations <- list(
 # 组合1:数据概览
  data_overview = function(df) {
    df %>%
      summarise(
        行数 = n(),
        列数 = ncol(.),
        缺失值数 = sum(is.na(.)),
        across(where(is.numeric), list(mean = mean, sd = sd), na.rm = TRUE)
      )
  },
  
 # 组合2:分组排名
  group_ranking = function(df, group_col, value_col, n = 3) {
    df %>%
      group_by({{group_col}}) %>%
      slice_max({{value_col}}, n = n) %>%
      ungroup()
  },
  
 # 组合3:数据质量检查
  data_quality_check = function(df) {
    df %>%
      summarise(
        across(everything(), ~ sum(is.na(.x)), .names = "{.col}_缺失数")
      ) %>%
      pivot_longer(everything(), names_to = "列名", values_to = "缺失数") %>%
      filter(缺失数 > 0) %>%
      arrange(desc(缺失数))
  }
)

# 3. 性能优化提示
performance_tips <- list(
  "使用 filter() 尽早减少数据量",
  "避免在 mutate() 中重复计算",
  "大数据量时考虑使用 data.table 或 dtplyr",
  "合理使用 .groups 参数控制分组行为",
  "善用 across() 函数批量处理列"
)

cat("💡 dplyr性能优化提示:\n")
for(i in seq_along(performance_tips)) {
  cat(sprintf("%d. %s\n", i, performance_tips[[i]]))
}

🎯 下一步学习建议

立即练习:

  • [ ] 用dplyr分析一个真实数据集
  • [ ] 尝试复现今天案例中的所有操作
  • [ ] 编写自己的数据处理流水线

继续学习:

  • [ ] 学习 07-数据清洗技巧|数据清洗技巧 - 处理脏数据
  • [ ] 学习 ggplot2数据可视化 - 让数据会说话

quote 💭 **学习感悟**

dplyr的核心哲学:

  • 🎯 一个函数做一件事 - 职责单一,易于理解
  • 🔗 管道串联操作 - 思路清晰,逻辑连贯
  • 📝 代码即文档 - 代码可读,自我解释
  • ⚡ 高效执行 - C++底层,性能优异

掌握了dplyr,你就掌握了数据处理的精髓! ✨


创建时间:2024-12-11
温度指数:⭐⭐⭐⭐⭐ (实战性强,案例完整)
预计学习时长:75-90分钟
下一步学习:数据清洗技巧 → ggplot2数据可视化

#R语言 #dplyr #数据操作 #数据处理 #管道操作 #数据分析 #tidyverse