5步将凌乱的数据处理成干净的表格。
1 第一步:了解数据、快速诊断
1.1 基础诊断和了解
Rows: 6
Columns: 8
$ `patient id` <chr> "P001", "P002", "P003", "P004", "P005", "P006"
$ `admission date` <chr> "2023/3/15", "2023-04-02", "20230510", "2023/5/18", "…
$ age_year <chr> "45", "62", "38", "-", "55", "71"
$ gender <chr> "男", "女", "M", "女", "男", "女"
$ sbp_mmhg <dbl> 128, 0, 136, 142, 118, 155
$ `glucose mg dL` <chr> "148", "85", "0", "189", "不详", "201"
$ diagnosis <chr> "糖尿病", "正常", "糖尿病前期", "糖尿病", "正常", "糖尿病"…
$ BMI <dbl> 28.5, 26.1, 0.0, 31.2, 27.8, NA
# ── 第二步:详细描述统计 ──────────────────────────────
skim(df)| Name | df |
| Number of rows | 6 |
| Number of columns | 8 |
| _______________________ | |
| Column type frequency: | |
| character | 6 |
| numeric | 2 |
| ________________________ | |
| Group variables | None |
Variable type: character
| skim_variable | n_missing | complete_rate | min | max | empty | n_unique | whitespace |
|---|---|---|---|---|---|---|---|
| patient id | 0 | 1 | 4 | 4 | 0 | 6 | 0 |
| admission date | 0 | 1 | 8 | 10 | 0 | 6 | 0 |
| age_year | 0 | 1 | 1 | 2 | 0 | 6 | 0 |
| gender | 0 | 1 | 1 | 1 | 0 | 3 | 0 |
| glucose mg dL | 0 | 1 | 1 | 3 | 0 | 6 | 0 |
| diagnosis | 0 | 1 | 2 | 5 | 0 | 3 | 0 |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| sbp_mmhg | 0 | 1.00 | 113.17 | 56.84 | 0 | 120.5 | 132.0 | 140.5 | 155.0 | ▂▁▁▂▇ |
| BMI | 1 | 0.83 | 22.72 | 12.83 | 0 | 26.1 | 27.8 | 28.5 | 31.2 | ▂▁▁▁▇ |
patient id admission date age_year gender sbp_mmhg
0 0 0 0 0
glucose mg dL diagnosis BMI
0 0 1
# 可视化缺失值分布(一图看清楚)
vis_miss(df)
# ── 第四步:检查重复行 ────────────────────────────────
sum(duplicated(df))[1] 0
df[duplicated(df), ] # 看具体是哪些重复行# A tibble: 0 × 8
# ℹ 8 variables: patient id <chr>, admission date <chr>, age_year <chr>,
# gender <chr>, sbp_mmhg <dbl>, glucose mg dL <chr>, diagnosis <chr>,
# BMI <dbl>
1.2 把诊断结果给DeepSeek V4
将以上结果中的glimpse(df)复制粘贴给DeepSeek V4,提示它帮你分析数据质量问题,并给出处理建议。具体的COSTAR提示词吐下所示:
【C·背景】 我有一份[数据名称的]数据,glimpse输出如下:
[把 glimpse(df) 的完整输出粘贴在这里]
【O·目标】 1. 分析这份数据存在哪些数据质量问题, 2. 按类型归类(日期格式、缺失值、数据类型、编码不一致等), 3. 给出优先处理顺序
【S·风格】 条目式列出,每个问题说明:问题描述 + 可能的影响 + 建议处理方法
【T·语气】 专业简洁,直接给可操作的建议,不需要解释基础概念
【A·受众】 有R基础,想用AI辅助做数据分析
【R·格式】 按优先级排序的问题清单,最后给一个推荐的处理顺序
DeepSeek V4会帮我们梳理出一份”数据清洗任务清单”,按照这个清单来处理,不会漏掉任何问题。
2 第二步:处理缺失值-让数据不再”有病”
缺失值处理是数据清洗里最需要判断力的环节。不同情况用不同策略,没有万能方法。
我的数据缺失情况如下(百分比): [粘贴 missing_rate 的输出]
数据特点:替换为自己的数据特点 - 这是一份横断面临床研究数据,共[N]例 - 结局变量是[变量名](二分类) - 分析目的是做逻辑回归
【O·目标】 根据每个变量的缺失率和临床意义,给出具体的缺失值处理方案, 包括:处理策略选择、代码实现、处理后验证
【S·风格】tidyverse 风格,保守处理原则(宁可多删不误导)
【T·语气】生态环境科学研究规范,解释每个决策的统计学和依据
【A·受众】准备投稿SCI的生态环境科学研究者
【R·格式】 1. 每个变量的处理方案(表格形式) 2. 完整的处理代码 3. 敏感性分析建议
3 第三步:列名规范化-让代码不再认不出变量
- 可使用
janitor::clean_names()函数快速规范化列名,统一小写,去掉特殊字符,空格变下划线。但对中文列名可能不太友好,建议先用英文列名,或者后续再重命名。 - 如果列不多,可以手动重命名,保持清晰有意义,避免过长或过短的名字。
- 也可以使用
COSTAR提示词让AI帮你生成规范的列名,尤其是当原始列名非常混乱时。
【C·背景】 我的R数据框有以下列名:
[粘贴 names(df) 的输出]
目标:转换为规范的英文小写下划线格式,变量名有实际含义
【O·目标】 生成一段 rename() 代码,把所有列名转换为规范的英文命名, 每个新列名后面加中文注释说明含义
【S·风格】tidyverse 管道写法
【R·格式】完整的 rename() 代码块,可以直接运行
4 第四步:数据类型转换-让每列数据都穿上合适的”衣服”
数据读进来之后,R 不一定能正确判断每列的类型。日期被读成字符串,分类变量被读成数字,数值被读成因子——这些都会导致后续分析出错。
【C·背景】 数据框 df 的 glimpse 输出如下: [粘贴 glimpse(df) 输出]
存在以下类型问题:[替换为自己的数据问题] - date_admission 列是字符型,包含多种日期格式(举例说明) - gender 列编码不统一(列出具体值) - age 列是字符型(因为包含”-“)
【O·目标】 生成完整的数据类型转换代码,处理上述所有问题
【S·风格】tidyverse 管道写法,一个 mutate() 块完成所有转换
【T·语气】关键参数加注释解释为什么这样写
【R·格式】完整可运行代码 + 最后加验证代码(table/class/sum(is.na()))
5 第五步:数据验证——确认清洗结果符合预期
- 基础验证:检查数据清洗后的分布是否与原始数据一致,是否存在异常值或数据丢失问题。
- 用 skimr 做数据质量报告:
skimr::skim()函数是summary()的替代方案,可快速提供数据框的广泛概述。 它处理所有类型的数据,根据数据框中的列类型调度一组不同的摘要函数。 - 保存清洗后的数据。
6 实际应用
6.1 构建”脏”数据
set.seed(42) # 设置随机种子以保证结果可重现
# 构造第一张表:患者基本信息(patient_info)
# 包含:缺失值、重复行、数据类型错误、空格、格式不统一
# fmt: skip
patient_info <- tibble(
patient_id = c(
"P001", "P002", "P003", "P004", "P005",
"P006", "P007", "P008", "P009", "P010",
"P003", "P011", "P012" # P003 重复了
),
name = c(
"张三", " 李四", "王五 ", "赵六", NA, ## 注意李四前面和王五后面有空格,NA为缺失值
"孙七", "周八", "吴九", "郑十", "王十一",
"王五", "钱十二", " 陈十三 " # 王五重复,陈十三前后都有空格
),
age = c(
28, 35, -5, 42, 55, # -5 是不合理的年龄
999, 38, NA, 31, 45, # 999 也不合理,还有一个 NA
50, 67, 29
),
gender = c(
"M", "F", "Male", "F", "M", # Male 和 M 格式不统一
"Female", "M", "f", "M", "F", # Female 和 F、f 和 F 不统一
"M", "M", NA
),
blood_pressure = c(
"120/80", "130/85", "140/90", "NA", "125/82", # "NA" 是字符串,不是真缺失
"135/88", "150", "128/84", "118/76", "132/86", # "150" 格式不对,缺少舒张压
"140/92", "122/78", "126/80"
),
admission_date = c(
"2024-01-15", "2024/02/20", "20240310", # 三种日期格式混用
"2024-04-05", "2024-05-12", "2024-06-08",
"2024-07-22", "2024-08-15", "2024.09.03", # 又一种格式
"2024-10-18", "2024-03-10", "2024-11-25",
"2024-12-01"
)
)
# 构造第二张表:实验室检查结果(lab_results)
# 包含:异常极端值、缺失值、ID 列名不同
# fmt: skip
lab_results <- tibble(
ID = c(
# 注意:这里列名叫 ID,不叫 patient_id
"P001", "P002", "P003", "P004", "P005",
"P006", "P007", "P008", "P009", "P010",
"P013", "P014" # P013和P014 在 patient_info 里没有
),
glucose = c(
95, 110, 450, 88, NA, # 450 是极端异常值
102, 97, 115, 0, 105, # 0 也不合理
98, 108
),
cholesterol = c(
180, 220, 195, NA, 240,
210, 185, -10, 200, 230, # -10 不合理
175, 205
),
hemoglobin = c(
13.5, 12.8, NA, 14.2, 11.0, # 缺失值
15.5, 99.9, 13.0, 12.5, 14.8, # 99.9 极端异常
13.2, 11.8
)
)
# 构造第三张表:随访记录(follow_up)
# 包含:一个患者多条记录、日期缺失
# fmt: skip
follow_up <- tibble(
patient_id = c(
"P001", "P001", "P002", "P003", "P004",
"P005", "P005", "P005", "P006", "P015" # P015 在其他表里都没有
),
visit_date = c(
"2024-03-01", "2024-06-15", "2024-04-20",
NA, "2024-05-10", "2024-06-01",
"2024-09-15", "2024-12-20",
"2024-07-30", "2024-08-05"),
status = c(
"好转", "稳定", "好转", "恶化", "好转",
"稳定", "好转", "好转", "恶化", "失访")
)