夜雨聆风学习资料网

ARTICLE · 1188478

拿到一份Excel数据,我用AI+R做了10项体检,发现5类隐藏问题(附代码)

拿到一份Excel数据,我用AI+R做了10项体检,发现5类隐藏问题(附代码)

一份数据,从能读取到能分析,中间究竟差了多少步?

上一篇文章,我分享了《用AI写R代码,为什么数据分析还是做不好?这5个坑,我反复见到》。

其中有一个观点,我想再强调一次:

AI能写R代码,不代表它能保证数据分析结果正确。

文章发布后,我也一直在思考一个问题:

如果读者已经知道数据分析需要避坑,那么下一步,应该怎么做?

我的答案是:拿一份真实数据,完整跑一遍。

今天,我用一个公开数据集,结合AI和R语言,带大家完成一次从数据体检、问题修复到结果输出的实战。

不讲复杂理论,不堆砌几十个R包。

我们只做一件事:

让一份数据,从“能打开”,变成“能检查、能分析、能复现”。

全文包含可运行的R代码。建议先收藏,后续可以对照自己的数据逐项检查。

01. 准备一份真实数据

今天使用的是R语言 modeldata 包中的 attrition 数据集。

这是一个常用于教学的员工流失分析数据集,包含1470条员工记录、31个变量。

例如:

  • Age:年龄
  • Department:部门
  • MonthlyIncome:月收入
  • JobSatisfaction:工作满意度
  • OverTime:是否加班
  • Attrition:是否离职

我们的研究问题是:

员工流失与哪些特征存在关联?

注意,这是一项探索性分析。我们可以研究变量之间的关联,但不能仅凭这些数据得出因果结论。

首先加载数据。

library(tidyverse)library(modeldata)data("attrition", package = "modeldata")df <- attritiondim(df)names(df)glimpse(df)

正常情况下,可以看到1470行、31列。

但这里有一个问题:

原始数据相对规整,不方便演示常见的数据质量错误。

因此,我专门制作一份教学用问题数据。

注意:以下缺失值、重复记录、异常值和错误编码均为人为注入,并不是说原始数据本身存在这些问题。

set.seed(20261015)df_dirty <- df# 问题1:年龄出现缺失值idx_age <- sample(  seq_len(nrow(df_dirty)),  size = 50)df_dirty$Age[idx_age] <- NA# 问题2:收入出现不合理值idx_income <- sample(  seq_len(nrow(df_dirty)),  size = 10)df_dirty$MonthlyIncome[idx_income] <- -999# 问题3:加班字段出现异常编码df_dirty$OverTime <- as.character(  df_dirty$OverTime)idx_ot <- sample(  seq_len(nrow(df_dirty)),  size = 20)df_dirty$OverTime[idx_ot] <- "Unknown"# 问题4:增加重复记录df_dirty <- bind_rows(  df_dirty,  df_dirty[1:15, ])# 问题5:年龄字段被错误转换为字符df_dirty$Age <- as.character(  df_dirty$Age)# 导出教学用Excelwritexl::write_xlsx(  df_dirty,"attrition_dirty.xlsx")

如果没有安装 writexl,可以先执行:

install.packages("writexl")

现在,我们得到一份包含5类典型问题的Excel数据。

接下来,不直接建模,而是先进行数据体检。

02. 用AI+R完成10项数据体检

我建议拿到任何一份新数据,都先检查以下10项。

检查项目
重点关注
① 数据规模
行数、列数是否符合预期
② 变量名称
是否重复、含义是否明确
③ 数据类型
数值、字符、因子是否正确
④ 缺失值
缺失数量、比例与分布
⑤ 重复记录
是否存在完全重复行
⑥ 异常数值
是否违反合理范围
⑦ 分类编码
是否出现非法类别
⑧ 数据分布
偏态、极端值和集中程度
⑨ 变量关系
是否存在明显异常关联
⑩ 分析准备
目标变量、研究设计与处理规则是否明确

这里特别提醒:

不是所有问题都能靠一行R代码自动判断。

例如,异常值是否应该删除、缺失值采用什么处理方法、统计模型是否合理,都需要结合业务背景。

下面先运行一段基础检查代码。

library(tidyverse)library(readxl)df_check <- read_excel("attrition_dirty.xlsx")# 1. 数据规模dim(df_check)# 2. 变量名称names(df_check)# 3. 数据结构glimpse(df_check)# 4. 缺失值数量colSums(is.na(df_check))# 5. 完全重复记录数量sum(duplicated(df_check))# 6. 年龄字段检查class(df_check$Age)# 7. 收入范围检查summary(df_check$MonthlyIncome)# 8. 加班分类检查table(  df_check$OverTime,  useNA = "ifany")# 9. 离职情况table(  df_check$Attrition,  useNA = "ifany")# 10. 查看数据摘要summary(df_check)

通过这轮检查,我们能够识别出前面人为注入的5类问题:

年龄缺失、收入异常编码、加班类别异常、重复记录、年龄类型错误。

这里还有一个细节:

由于我们将年龄字段转成了字符,读取Excel后,R不会自动知道它原本应该是数值变量。

这就是为什么我反复强调:

数据分析不能只依赖AI生成代码,还必须理解字段的业务含义。

03. 修复5类问题:不要一上来就删除数据

发现问题之后,接下来就是清洗。

但清洗数据,并不是简单地把所有异常记录删除。

我们需要先制定规则。

今天采用以下教学策略:

  • 完全重复记录:删除重复副本;
  • 年龄字段:恢复数值类型;
  • 年龄缺失:保留缺失,并用非缺失样本的中位数演示简单插补;
  • 收入中的 -999:视为人为设置的缺失编码,转换为 NA;
  • 加班中的 Unknown:保留为明确的未知类别,不擅自判断为“Yes”或“No”。

执行代码:

df_clean <- df_check %>%  distinct() %>%  mutate(    Age = as.numeric(Age),    MonthlyIncome = if_else(      MonthlyIncome == -999,NA_real_,      as.numeric(MonthlyIncome)    ),    OverTime = factor(      OverTime,      levels = c("No","Yes","Unknown"      )    )  )# 演示年龄中位数插补age_median <- median(  df_clean$Age,  na.rm = TRUE)df_clean <- df_clean %>%  mutate(    Age = replace_na(      Age,      age_median    )  )

这里必须强调两个专业问题。

第一,收入中的-999为什么转成NA?

因为我们在教学数据生成阶段,明确知道它是人为设置的异常编码。

如果换成真实业务数据,就必须先确认字段字典或业务规则,不能看到负数就随意删除。

第二,为什么年龄采用中位数插补?

这是为了演示基本操作,不代表中位数插补适用于所有研究。

真实科研中,应结合缺失比例、缺失机制和分析目的选择方法,必要时考虑多重插补及敏感性分析。

如果后续要训练机器学习模型,涉及从数据学习参数的插补、标准化和特征选择,应该在训练集或交叉验证的相应训练折内完成,避免数据泄漏。

正确的数据清洗,不是让数据变得好看,而是让每一步处理都有依据。

04. 清洗之后,开始做描述性统计

数据准备完成后,我们先回答一个简单问题:

不同加班状态下,员工流失比例是否存在差异?

这里选择 OverTime 和 Attrition 两个变量。

summary_table <- df_clean %>%  filter(    OverTime %in% c("Yes", "No")  ) %>%  count(    OverTime,    Attrition  ) %>%  group_by(OverTime) %>%  mutate(    proportion = n / sum(n)  ) %>%  ungroup()print(summary_table)

这段代码可以计算不同加班组内部的离职人数和比例。

接下来绘制图表。

ggplot(  summary_table,  aes(    x = OverTime,    y = proportion,    fill = Attrition  )) +  geom_col(    position = "fill"  ) +  scale_y_continuous(    labels = scales::percent  ) +  labs(    title = "不同加班状态下的员工流失构成",    x = "是否加班",    y = "组内比例",    fill = "是否离职"  ) +  theme_minimal(    base_size = 14  )

注意:这里展示的是描述性关联,不代表加班一定导致员工离职。

如果要进一步分析关联强度,还需要结合变量类型、研究设计、潜在混杂因素等,选择合适的统计方法。

另外,Unknown 类别在此被排除在分组比较之外,正式分析时应报告排除规则及对应样本量。

05. AI在这个工作流中,应该扮演什么角色?

很多人使用AI做数据分析,习惯直接输入:

“帮我分析这份数据。”

这个提问太宽泛。

我更推荐把AI作为数据分析助手,让它协助完成明确的任务,同时保留人的审核环节。

例如,下面这段提示词可以反复使用。

AI+R数据体检通用Prompt:

你是一名具有统计学和R语言经验的数据分析助手。我正在使用R语言分析一份Excel数据。请按照以下步骤协助我:1. 检查数据结构与字段类型2. 统计各变量缺失值数量和比例3. 检查完全重复记录4. 识别可能存在的异常数值5. 检查分类变量的异常编码6. 输出连续变量的描述性统计7. 检查目标变量的类别分布8. 提醒可能存在的数据泄漏风险9. 给出适合当前研究问题的分析建议10. 生成可复现的R代码要求:- 优先使用tidyverse生态- 不得虚构数据或统计结果- 不得擅自删除异常样本- 对每个清洗步骤解释原因- 对不确定的业务规则明确提出问题- 代码应尽量完整、可运行- 区分数据事实、统计假设和分析建议

这段Prompt真正有价值的地方,不是让AI一次性输出更多代码。

而是给AI建立清晰的工作边界。

让AI执行具体任务,让人负责关键判断。

这才是AI+R工作流应该发挥的作用。

06. 最后一步:把分析过程变成可复现报告

做完数据清洗和统计分析,还不算结束。

因为科研和实际工作中,分析结果往往需要交给导师、同事或客户。

如果只有一堆零散的R代码,后续修改、复查和复现都很困难。

我建议使用Quarto组织分析报告。

一个基础报告可以包含:

analysis-report.qmd1. 研究问题2. 数据来源3. 数据体检4. 数据清洗规则5. 描述性统计6. 数据可视化7. 分析结论与局限性

通过Quarto,可以把代码、图表、文字解释和分析结果整合在同一份文档中。

例如,在配置好Quarto环境后:

quarto render analysis-report.qmd --to html

就可以生成HTML报告。

需要注意,这里的命令是报告生成示例。要得到完整报告,还需要先编写对应的 .qmd 文件。

对我而言,真正完整的数据分析交付,不只是得到几张图。

而是能够提供:

数据说明 + 清洗规则 + 可运行代码 + 分析结果 + 可复现报告。

07. 从会写R代码,到拥有一套自己的RAI工作流

回顾今天的案例,我们做了什么?

第一步,准备公开数据,并构造教学问题。

第二步,完成10项基础检查。

第三步,识别并处理5类人为注入的数据质量问题。

第四步,完成描述性统计和可视化。

第五步,使用AI辅助检查代码与分析思路。

第六步,建立可复现报告的组织方式。

整个过程可以概括为:

研究问题 → 数据体检 → 数据清洗 → 统计分析 → 可视化 → 报告交付。

这也是我一直在探索的RAI工作流。

过去13年,我一直在使用R语言解决数据分析问题。

进入AI时代后,我越来越确信:

真正值得积累的,不只是某一段R代码,而是一套能够反复使用、不断优化的数据分析方法。

AI让编程更高效。

R语言让分析更加灵活。

而完整的工作流,才能让我们持续解决真实问题。

08. 免费领取:AI+R数据体检与分析工作流

为了方便大家跟着本文实操,我准备整理一份:

《AI+R数据体检与分析工作流 V1.0》

计划包含:

  • 公开案例数据与教学用问题数据
  • 数据体检R代码
  • 数据清洗R代码
  • 描述性统计与绘图示例
  • AI辅助数据分析Prompt
  • 可复现报告模板

联系我们,回复「工作流」,获取资料领取说明。

如果你还没有领取上一篇文章中的《AI+R数据分析10项体检清单》,也可以回复 「体检」。

最后,我想问大家一个问题:

如果有一套工具,可以让你导入自己的Excel数据,自动完成基础数据检查,并生成可编辑的R分析报告,你最希望它解决什么问题?

A. 自动发现数据质量问题

B. 自动生成数据清洗R代码

C. 辅助选择统计分析方法

D. 自动生成科研图表

E. 自动整理可复现分析报告

欢迎在评论区回复A、B、C、D或E。

你的真实需求,将帮助我决定下一步优先开发哪些功能。

AI时代,真正有价值的不是写出更多代码,而是用更可靠的工作流,完成更多有意义的数据分析。

—— RAI王博士

相关学习资料