Evan の Logbook
✨ Updates
🎨 Style Guide
🧠 Creative Resources
🗒️ Mind Notes
🧭 Knowbase
📘 SOPs
🩺 Medical Research
🛠️ Tech Chronicles
💰 Fortune Blueprint
📈 R Visionary
📊 Statistics
🖼️ BioVis
📊用 readxl 读取 Excel:实践指南 + 可复用增强函数
type
status
date
slug
summary
tags
category
icon
password
comment
Excel 在日常数据工作中几乎无处不在,但它既不是数据库,也不是干净的 CSV。作为“数据入口”,我们需要一个稳定、明确、可控的读取方案。
readxl 的优势就在于:- 无需 Java/Excel 依赖,跨平台稳定(Windows/macOS/Linux)。
- 对 Excel 日期序列、数值、文本等有明确的解析策略。
- 参数简洁,和 tidyverse 生态契合。
这篇文章包含三部分:
read_excel()的正确姿势(含“读前 checklist”)
- 增强函数
read_excel_flex()(源码 + 设计思路 + 返回值约定)
- 典型业务场景配方与常见坑排查
1) read_excel() 正确姿势
1.1 最小例子与核心参数
几点实用提醒:
- 指定
sheet与range能极大降低脏数据干扰(比如页眉说明、合计行、图例等)。
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。
- 脏行/多表头:务必用
skip与range切准数据区;必要时先在 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...
YouTube 使用笔记