📊用 readxl 读取 Excel:实践指南 + 可复用增强函数

type
status
date
slug
summary
tags
category
icon
password
comment
Excel 在日常数据工作中几乎无处不在,但它既不是数据库,也不是干净的 CSV。作为“数据入口”,我们需要一个稳定、明确、可控的读取方案。readxl 的优势就在于:
  • 无需 Java/Excel 依赖,跨平台稳定(Windows/macOS/Linux)。
  • 对 Excel 日期序列、数值、文本等有明确的解析策略
  • 参数简洁,和 tidyverse 生态契合。
这篇文章包含三部分:
  1. read_excel() 的正确姿势(含“读前 checklist”)
  1. 增强函数 read_excel_flex()(源码 + 设计思路 + 返回值约定)
  1. 典型业务场景配方与常见坑排查

1) read_excel() 正确姿势

1.1 最小例子与核心参数

几点实用提醒:
  • 指定 sheetrange 能极大降低脏数据干扰(比如页眉说明、合计行、图例等)。
  • col_types 优先级高于自动猜测:对关键列(如编码ID手机号邮编)强制设为 "text",保留前导零与原始格式。
  • Excel 日期:Excel 用“序列数”表示日期(Windows 常见原点是 1899-12-30;部分工作簿会使用 1904 系统)。readxl 会自动识别大多数情况并转换为 Date/POSIXct;若发现被读成 numeric,再手动转换即可。

1.2 读前 checklist(很管用)

  • 这份表有统一表头吗?表头是否只有一行
  • 是否存在合并单元格/跨行说明?(尽量在 Excel 里“另存为原始数据”)
  • 需不需要指定范围只读有效数据区?
  • 哪些列需要保留原样(ID、编码、账号、邮编、SKU)→ col_types = "text"
  • 是否包含日期时间时区信息?
  • 空值用什么标记(""/NA//N/A)?需要在 na统一纳入

2) 增强函数:read_excel_flex()(更可控、更友好)

为了让“读取→清洗→进入分析流”更顺滑,我写了一个增强封装,read_excel() 不做魔改的前提下补上常用能力:
  • CLI 反馈:读取过程更明确(展示 sheet 列表、成功/失败提示)。
  • 列名清理(可选):用 janitor::clean_names() 统一为snake_case,去空格与奇怪符号。
  • 类型兜底:支持显式 col_types;若不指定,再做一次 readr::type_convert() 二次优化(可选)。
  • 校验与报错:文件存在性、缺包提醒、sheet 合法性、range 提示。
  • 参数命名贴近 readxl:降低心智负担。
🔎 说明:readxl 有自己的类型猜测策略;本函数不改变底层逻辑,只是在边界条件与使用体验上更稳。

2.1 源码(可直接用)

2.2 设计思路(你未来维护时会很有用)

  • 职责单一:只做“读取 + 最轻清理”,不在函数里做数据变形(如长宽变换、分组、衍生列),把责任边界切清。
  • 行为可预测:尽量贴近 read_excel() 的语义,新增参数默认关闭(如 post_type_convert)。
  • 硬性兜底:对 ID/编码等敏感列,建议在调用时显式 col_types,而不是依赖猜测。
  • CLI 可关闭:批量任务中设置 verbose = FALSE,避免刷屏。

3) 典型业务场景配方(直接拷贝改变量名就能用)

3.1 指定列类型以保留前导零(强烈推荐)

3.2 只读有效数据区(跳过页眉说明、合计)

3.3 多个 sheet 合并为一张表(加来源列)

3.4 读后“轻清理”:列名统一、类型稳妥、日期正确

3.5 Excel 日期读成了数字?按系统原点转换

readxl 多数情况下会自动转换;若遇到“数字日期”,可能是列类型被你强制成了 "numeric" 或工作簿标记不一致。

4) 常见坑点速查(现场排障更快)

  • 列名不规则:空格/中文括号/重复名 → 打开 clean_names = TRUE,统一成 snake_case
  • 脏行/多表头:务必用 skiprange 切准数据区;必要时先在 Excel 清理
  • 合并单元格readxl 读取的是单元格值,合并不会自动“广播”到空白单元格;需要在 R 里手动 tidyr::fill()
  • 数值中混有符号$1,234/1,234元):读入为字符后用 readr::parse_number() 清洗。
  • ID/邮编/手机号被科学计数法:务必用 col_types = "text"
  • 日期/时间/时区:读入后统一转 Date/POSIXct;跨系统存储时优先使用 UTC。
  • 尾部合计/备注readxl 没有“跳过尾部行”的参数,range 限定或读入后过滤。

5) 结语

这套做法把“读取 Excel”从一次性的手工操作,变成可复用、可移植、可维护的流程:
读入前有 checklist,读入时有增强函数兜底,读入后有明确的清理步骤和类型转换策略。
你可以把 read_excel_flex() 放进自己的 utils 包,在所有项目里一键复用。
Prev
AUCell 流程笔记(GSE60361 小鼠脑示例)
Next
make_date() & make_datetime():从字段构造时间对象
Loading...
Article List
Evan の Logbook
✨ Updates
🎨 Style Guide
🧠 Creative Resources
🗒️ Mind Notes
🧭 Knowbase
📘 SOPs
🩺 Medical Research
🛠️ Tech Chronicles
💰 Fortune Blueprint
📈 R Visionary
📊 Statistics
🖼️ BioVis