Chapter 3 第三章 数据加工
数据加工(data wrangling)是指对原始数据集进行一系列处理,以消除数据中的错误,选择合适的变量,合并不同数据集,调整数据格式,为后续的探索性数据分析(下一章)做好准备。本章主要介绍数据清理、变量筛选、数据合成、数据塑形等数据处理操作。在学习数据处理之前,我们需要对数据与变量的类型有所了解。
3.4 课堂任务
# 数据处理函数大合集
library(tidyverse)
########################################
# ✔ dplyr 1.1.3 ✔ readr 2.1.4
# ✔ forcats 1.0.0 ✔ stringr 1.5.1
# ✔ ggplot2 3.4.4 ✔ tibble 3.2.1
# ✔ lubridate 1.9.3 ✔ tidyr 1.3.0
# ✔ purrr 1.0.2
#########################################任务3.3 数据清洁
# 创建含有错误值的数据
set.seed(123) # 设置随机种子以确保可重复性
df_errors <- data.frame(Student_ID = 1:100,
Listening_Score = sample(-5:100, 100, replace = TRUE),
Speaking_Score = sample(0:103, 100, replace = TRUE),
Reading_Score = sample(c(0:100, NA), 100, replace = TRUE),
Writing_Score = sample(0:100, 100, replace = TRUE),
Age = sample(c(18:40, NA), 100, replace = TRUE),
Gender = sample(c("Male", "Female"), 100, replace = TRUE))%>%
mutate(Writing_Score = case_when(
Student_ID %in% c(5, 20, 50) ~ Writing_Score + 50, # 添加异常值
TRUE ~ Writing_Score ),
Writing_Score = case_when(
Student_ID %in% c(3, 23, 54,67) ~ Writing_Score - 50, # 添加异常值
TRUE ~ Writing_Score ))
# 使用 drop_na() 函数删除含有缺失值的行
df_clean <- df_errors %>% drop_na()
# 使用均值插值法填补缺失值
df_interpolated <- df_errors %>%
mutate(Reading_Score_new = ifelse(is.na(Reading_Score),
mean(Reading_Score, na.rm = TRUE),
Reading_Score))
# 使用中位数插值法填补缺失值
df_interpolated_median <- df_errors %>%
mutate(Reading_Score_new = ifelse(is.na(Reading_Score),
median(Reading_Score, na.rm = TRUE), Reading_Score))
# 使用 filter() 函数排除异常值
df_clean <- df_clean %>%
filter(Listening_Score >= 0 & Speaking_Score <= 100 & Reading_Score <= 100)
# 过滤掉超过2个标准差的异常值
df_clean_sd <- df_errors %>%
filter(Writing_Score >= mean(Writing_Score, na.rm = TRUE) - 2 * sd(Writing_Score, na.rm = TRUE) &
Writing_Score <= mean(Writing_Score, na.rm = TRUE) + 2 * sd(Writing_Score, na.rm = TRUE))
# 使用四分位距法来识别并排除异常值
df_clean_iqr <- df_errors %>%
filter(Writing_Score >= quantile(Writing_Score, 0.25, na.rm = TRUE) - 1.5 * IQR(Writing_Score, na.rm = TRUE) &
Writing_Score <= quantile(Writing_Score, 0.75, na.rm = TRUE) + 1.5 * IQR(Writing_Score, na.rm = TRUE))# 创建包含各种文本问题的数据框
text_problems <- data.frame(ID = 1:4,
Problem_Type = c("拼写错误", "冗余词汇", "标点符号", "词性标签"),
Original_Text = c("Ths is an exmple of text with splling errors.",
"This is is an example example of redundant redundant words.",
"Clean the text; remove: punctuations!",
"This_DT is_VBZ an_DT example_NN."), stringsAsFactors = FALSE)
# 逐行处理文本问题
cleaned_text <- text_problems %>%
mutate(Cleaned_Text = case_when(
Problem_Type == "拼写错误" ~ str_replace_all(Original_Text,
c("Ths" = "This", "exmple" = "example",
"splling" = "spelling")),
Problem_Type == "冗余词汇" ~ str_replace_all(Original_Text, "\\b(\\w+)\\s+\\1\\b", "\\1"),
Problem_Type == "标点符号" ~ str_replace_all(Original_Text, "[[:punct:]]", ""),
Problem_Type == "词性标签" ~ str_replace_all(Original_Text, "_[A-Z]+", "")
))任务3.5 数据塑形
# 生成一个二语学术写作数据集
set.seed(123) # 设置随机种子,以确保结果可复现
academic_writing_data <- tibble(
student_id = 1:10, # 学生ID
native_language = sample(c("Chinese", "Spanish", "French", "Russian", "German", "Italian"), 10, replace = TRUE), # 母语
second_language = sample(c("English", "Chinese", "Spanish", "French", "German", "Italian"), 10, replace = TRUE), # 二语
essay1_length = sample(200:2000, 10, replace = TRUE), # 论文1长度
essay2_length = sample(200:2000, 10, replace = TRUE), # 论文2长度
essay3_length = sample(200:2000, 10, replace = TRUE), # 论文3长度
)
# 把essay1_length、essay2_length和essay3_length三列汇总到一列中
long_data <- gather(academic_writing_data,
essay, length,
essay1_length:essay3_length)
# 转回宽格式
wide_data <- spread(long_data, essay, length)任务3.6 数据整合
# 创建学生基本信息数据集
student_info <- data.frame(
Student_ID = c("123456789012", "123456789013", "123456789014"),
Name = c("Alice", "Bob", "Charlie"),
Age = c(20, 21, 22))
# 创建学生成绩数据集
student_scores <- data.frame(
ID = c("89012", "89013", "89014", "89015"), # ID仅包含身份证后六位
Math_Score = c(85, 90, 78, 88),
English_Score = c(82, 76, 91, 80))
# 标准化ID列
student_scores <- student_scores %>%
mutate(ID = paste0("1234567", ID)) # 假设前十位是固定的
# 合并数据集
merged_data <- student_scores %>%
full_join(student_info , by = c("ID"="Student_ID")) # 使用full_join合并
merged_data.cleaned <- merged_data %>%
filter(!is.na(Name))