Skip to content

R dplyr 数据整理流水线:从原始数据到干净表格

问题

分析师常常耗费大量时间编写重复的 R 循环来清洗数据集。结果是脚本脆弱、列结构前后不一致,而且每次有新文件到来时迭代都很缓慢。

加剧

手工步骤会层层堆叠:选错列、变换顺序错误,或者忘记区分 factor 与 character。每一次失误都意味着重跑流程,并且有把错误指标传递到下游仪表盘的风险。

解决思路

采用一套统一的 dplyr 流水线,让逻辑贴近 SQL,同时保持每一步变换都可读可追踪。下面这些动词覆盖了列选择、行过滤、新特征构造、聚合汇总、排序以及安全的连接操作,保证数据在建模或可视化前已经整洁有序。

核心流水线示例

library(dplyr)
 
clean_sales <- raw_sales %>%
  mutate(
    region = as.character(region),        # avoid accidental factor levels
    revenue = price * quantity
  ) %>%
  filter(!is.na(revenue), revenue > 0) %>%
  select(order_id, region, revenue, channel, order_date) %>%
  arrange(desc(revenue)) %>%
  group_by(region, channel) %>%
  summarise(
    orders = n(),
    revenue = sum(revenue),
    avg_order = mean(revenue),
    .groups = "drop"
  )

dplyr 动词与 SQL 等价关系

dplyr verb用途SQL 类比速记说明
select()保留或重命名列SELECT col1, col2使用 everything() 可快速重排列顺序。
filter()行子集筛选WHERE condition结合 %in% 处理多值匹配。
mutate()新增 / 变换列SELECT col1, col2*2 AS col2x使用 if_else() 保持返回类型稳定。
summarise() + group_by()分组统计指标GROUP BY ...添加 .groups = "drop" 以取消分组。
arrange()对行排序ORDER BY使用 desc() 实现降序。
left_join()用维表补充字段LEFT JOIN保持连接键的类型一致(character 与 factor 不要混用)。
bind_rows() / bind_cols()纵向堆叠或横向拼接表UNION ALL / 列拼接纵向堆叠前确保表结构一致。

Join 与 bind 的一目了然对比

# Join:根据维表补充列
sales_with_regions <- sales %>%
  left_join(region_lookup, by = "region_id")
 
# Bind:堆叠相同表结构
all_sales <- bind_rows(sales_2023, sales_2024)

避免 factor 与编码陷阱

  • 在做 join 之前,将标识类字段转换为 character,避免因水平不匹配而出错。
  • 如果从 CSV 读取时被隐式解析成了 factor,可用 mutate(across(where(is.factor), as.character)) 批量转换。
  • 在分组前用 stringr::str_trimtolower 统一文本格式,避免同一类别被拆成多个名称。

快速上手模板

prep_data <- function(df) {
  df %>%
    mutate(across(where(is.factor), as.character)) %>%
    filter(!is.na(key_id)) %>%
    distinct() %>%
    select(key_id, everything())
}

导出前检查清单

  • 已显式选择并排好列顺序。
  • 关键 join 使用了类型一致的键,并在需要时用清晰的后缀区分(如 suffix = c(".src", ".lkp"))。
  • 汇总步骤已通过 .groups = "drop" 解除分组,避免后续步骤行为异常。
  • 输出只包含干净、易读的字段,能够直接用于绘图或建模。

相关指南