最简R语言教程-数据处理通用流程

文档沟通和COSTAR提示词

R语言
文档沟通
ai提示词
COSTAR
数据处理
Author

Lee

Published

June 22, 2026

5步将凌乱的数据处理成干净的表格。

library(tidyverse)
library(skimr) # 数据概览
library(janitor)
library(naniar) # 处理缺失值

1 第一步:了解数据、快速诊断

1.1 基础诊断和了解

df <- read_csv("D:/Myblog/datas/P_data.txt") # 也可以读csv,看看哪个更干净

# ── 第一步:看数据结构 ────────────────────────────────
# 这行最重要,结果要粘给DeepSeek V4
glimpse(df)
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)
Data summary
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 ▂▁▁▁▇
# ── 第三步:缺失值全貌 ────────────────────────────────
# 每列缺失值数量
colSums(is.na(df))
    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提示词吐下所示:

Important使用COSTAR提示词分析数据质量问题

【C·背景】 我有一份[数据名称的]数据,glimpse输出如下:

[把 glimpse(df) 的完整输出粘贴在这里]

【O·目标】 1. 分析这份数据存在哪些数据质量问题, 2. 按类型归类(日期格式、缺失值、数据类型、编码不一致等), 3. 给出优先处理顺序

【S·风格】 条目式列出,每个问题说明:问题描述 + 可能的影响 + 建议处理方法

【T·语气】 专业简洁,直接给可操作的建议,不需要解释基础概念

【A·受众】 有R基础,想用AI辅助做数据分析

【R·格式】 按优先级排序的问题清单,最后给一个推荐的处理顺序

DeepSeek V4会帮我们梳理出一份”数据清洗任务清单”,按照这个清单来处理,不会漏掉任何问题。

2 第二步:处理缺失值-让数据不再”有病”

缺失值处理是数据清洗里最需要判断力的环节。不同情况用不同策略,没有万能方法。

Important使用COSTAR提示词制定缺失值处理方案

我的数据缺失情况如下(百分比): [粘贴 missing_rate 的输出]

数据特点:替换为自己的数据特点 - 这是一份横断面临床研究数据,共[N]例 - 结局变量是[变量名](二分类) - 分析目的是做逻辑回归

【O·目标】 根据每个变量的缺失率和临床意义,给出具体的缺失值处理方案, 包括:处理策略选择、代码实现、处理后验证

【S·风格】tidyverse 风格,保守处理原则(宁可多删不误导)

【T·语气】生态环境科学研究规范,解释每个决策的统计学和依据

【A·受众】准备投稿SCI的生态环境科学研究者

【R·格式】 1. 每个变量的处理方案(表格形式) 2. 完整的处理代码 3. 敏感性分析建议

3 第三步:列名规范化-让代码不再认不出变量

  • 可使用janitor::clean_names()函数快速规范化列名,统一小写,去掉特殊字符,空格变下划线。但对中文列名可能不太友好,建议先用英文列名,或者后续再重命名。
  • 如果列不多,可以手动重命名,保持清晰有意义,避免过长或过短的名字。
  • 也可以使用COSTAR提示词让AI帮你生成规范的列名,尤其是当原始列名非常混乱时。
Important使用COSTAR提示词生成规范列名

【C·背景】 我的R数据框有以下列名:

[粘贴 names(df) 的输出]

目标:转换为规范的英文小写下划线格式,变量名有实际含义

【O·目标】 生成一段 rename() 代码,把所有列名转换为规范的英文命名, 每个新列名后面加中文注释说明含义

【S·风格】tidyverse 管道写法

【R·格式】完整的 rename() 代码块,可以直接运行

4 第四步:数据类型转换-让每列数据都穿上合适的”衣服”

数据读进来之后,R 不一定能正确判断每列的类型。日期被读成字符串,分类变量被读成数字,数值被读成因子——这些都会导致后续分析出错。

Important使用COSTAR提示词生成列类型转换代码

【C·背景】 数据框 df 的 glimpse 输出如下: [粘贴 glimpse(df) 输出]

存在以下类型问题:[替换为自己的数据问题] - date_admission 列是字符型,包含多种日期格式(举例说明) - gender 列编码不统一(列出具体值) - age 列是字符型(因为包含”-“)

【O·目标】 生成完整的数据类型转换代码,处理上述所有问题

【S·风格】tidyverse 管道写法,一个 mutate() 块完成所有转换

【T·语气】关键参数加注释解释为什么这样写

【R·格式】完整可运行代码 + 最后加验证代码(table/class/sum(is.na()))

5 第五步:数据验证——确认清洗结果符合预期

  1. 基础验证:检查数据清洗后的分布是否与原始数据一致,是否存在异常值或数据丢失问题。
  2. skimr 做数据质量报告:skimr::skim()函数是summary()的替代方案,可快速提供数据框的广泛概述。 它处理所有类型的数据,根据数据框中的列类型调度一组不同的摘要函数。
  3. 保存清洗后的数据。
Important数据清洗的总体提示词

我有[X]张数据:分别为[数据集名称]。请帮我做完整的数据清洗:

  1. 扫描并处理缺失值(包括字符串”NA”等伪缺失值)
  2. 检测并处理异常值(年龄、血糖、胆固醇、血红蛋白)
  3. 统一性别编码为 M/F
  4. 统一日期格式
  5. 去除重复行三张表按[键列]合并
  6. 输出清洗前后的对比报告

使用 tidyverse 风格,每行加中文注释

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(
    "好转", "稳定", "好转", "恶化", "好转", 
    "稳定", "好转", "好转", "恶化", "失访")
)

6.2 缺失值处理

6.2.1 搞清楚缺失值有多少,哪里缺了

# 每列缺失数量占比
missing_summary <- patient_info |>
  summarise(across(everything(), \(x) sum(is.na(x)))) |> # 每列NA计数
  pivot_longer(everything(), names_to = "变量", values_to = "缺失数") |>
  mutate(缺失率 = paste0(round(缺失数 / nrow(patient_info) * 100, 1), "%"))
missing_summary
# A tibble: 6 × 3
  变量           缺失数 缺失率
  <chr>           <int> <chr> 
1 patient_id          0 0%    
2 name                1 7.7%  
3 age                 1 7.7%  
4 gender              1 7.7%  
5 blood_pressure      0 0%    
6 admission_date      0 0%    
# 找出每列中的假缺失值,如空字符串或“不知道”、“不详”等,或者"NA"字符串
patient_info |>
  filter(if_any(everything(), \(x) x %in% c("", "不知道", "不详", "NA")))
# A tibble: 1 × 6
  patient_id name    age gender blood_pressure admission_date
  <chr>      <chr> <dbl> <chr>  <chr>          <chr>         
1 P004       赵六     42 F      NA             2024-04-05    

6.2.2 处理伪缺失值

patient_info_v2 <- patient_info |>
  mutate(
    blood_pressure = na_if(blood_pressure, "NA"),
    # 统一处理所有字符列中的空字符串和"null"
    across(where(is.character), \(x) na_if(x, "")),
    across(where(is.character), \(x) na_if(x, "null"))
  )
patient_info_v2 |> summarise(across(everything(), \(x) sum(NA)))
# A tibble: 1 × 6
  patient_id  name   age gender blood_pressure admission_date
       <int> <int> <int>  <int>          <int>          <int>
1         NA    NA    NA     NA             NA             NA

6.2.3 缺失值处理的策略

  1. 策略1:直接删除,适合缺失率<5% 且随机缺失的情况。
  2. 策略2:使用均值/中位数/众数填充,适合数值型和分类型变量。
  3. 策略3:标记缺失,适合缺失值本身有意义的情况。

核心原则:不要默认删除,先判断缺失机制(完全随机缺失 MCAR / 随机缺失 MAR / 非随机缺失 MNAR),再选策略。

# 策略1:直接删除
data_drop <- patient_info_v2 |> filter(!is.na(name))
data_drop
# A tibble: 12 × 6
   patient_id name         age gender blood_pressure admission_date
   <chr>      <chr>      <dbl> <chr>  <chr>          <chr>         
 1 P001       "张三"        28 M      120/80         2024-01-15    
 2 P002       " 李四"       35 F      130/85         2024/02/20    
 3 P003       "王五 "       -5 Male   140/90         20240310      
 4 P004       "赵六"        42 F      <NA>           2024-04-05    
 5 P006       "孙七"       999 Female 135/88         2024-06-08    
 6 P007       "周八"        38 M      150            2024-07-22    
 7 P008       "吴九"        NA f      128/84         2024-08-15    
 8 P009       "郑十"        31 M      118/76         2024.09.03    
 9 P010       "王十一"      45 F      132/86         2024-10-18    
10 P003       "王五"        50 M      140/92         2024-03-10    
11 P011       "钱十二"      67 M      122/78         2024-11-25    
12 P012       " 陈十三 "    29 <NA>   126/80         2024-12-01    

TODO: https://mp.weixin.qq.com/s/ZBcAd1v0FLvSS4mNMP5Stg