如何高效读取不同扩展名本地文件并存储为data frame列表?
问题解答
一、无需for循环的文件读取方案
可以用purrr包的map()函数替代for循环,它能更简洁地遍历文件列表并应用自定义读取逻辑。先定义一个根据扩展名选择读取方式的函数,再用map()批量处理所有文件。
代码实现
library(dplyr) library(readxl) library(XML) library(purrr) # 定义自定义读取函数 read_file_by_ext <- function(file_path) { if (grepl("\\.csv$", file_path)) { read.csv(file_path, sep = "\t") } else if (grepl("\\.xls$", file_path)) { # 处理伪装成xls的HTML文件 readHTMLTable(file_path)$tblMain } else if (grepl("\\.xlsx$", file_path)) { read_excel(file_path) } else { stop("不支持的文件格式") } } # 获取文件列表(修正正则匹配,转义特殊字符.) files <- list.files(path = "data", recursive = TRUE, pattern = "\\.(csv|xls|xlsx)$", full.names = TRUE) # 批量读取到列表 df_list <- map(files, read_file_by_ext) # 可选:给列表元素命名为文件名,方便后续索引 names(df_list) <- basename(files)
说明:map()会自动遍历files中的每个路径,将结果收集到列表中,逻辑和原for循环一致,但代码更简洁易读。如果文件数量较多,还可以用map_parallel()实现并行读取来提速。
二、创建可复现的本地文件读取示例
要让他人复现你的读取流程,需要生成模拟测试文件并配套完整读取代码,步骤如下:
1. 创建测试目录结构
先复刻真实场景的子目录:
# 创建目录,showWarnings=FALSE避免重复创建时报错 dir.create("data/Bills", recursive = TRUE, showWarnings = FALSE) dir.create("data/Usages", recursive = TRUE, showWarnings = FALSE)
2. 生成模拟数据并写入对应格式文件
# 模拟CSV数据 csv_data <- tibble(AccountID = 1:3, Amount = c(100, 200, 150), Date = Sys.Date() - 1:3) write.csv(csv_data, "data/Bills/BillHistory_Account1.csv", sep = "\t", row.names = FALSE) # 模拟伪装成xls的HTML表格数据 html_content <- ' <table id="tblMain"> <tr><th>UsageID</th><th>Usage</th><th>Date</th></tr> <tr><td>1</td><td>50</td><td>2024-01-01</td></tr> <tr><td>2</td><td>75</td><td>2024-01-02</td></tr> </table> ' writeLines(html_content, "data/Bills/BillHistory_2.xls") # 模拟XLSX数据 xlsx_data <- tibble(UsageID = 3:4, Usage = c(60, 80), Date = Sys.Date() - 2:1) write_xlsx(xlsx_data, "data/Usages/UsageHistory_4.xls.xlsx")
3. 完整可复现代码
将测试文件生成逻辑和读取逻辑整合,他人运行即可自动创建测试环境并完成读取:
# 加载依赖包 library(dplyr) library(readxl) library(XML) library(purrr) # ---- 生成测试文件 ---- dir.create("data/Bills", recursive = TRUE, showWarnings = FALSE) dir.create("data/Usages", recursive = TRUE, showWarnings = FALSE) # 写入CSV csv_data <- tibble(AccountID = 1:3, Amount = c(100, 200, 150), Date = Sys.Date() - 1:3) write.csv(csv_data, "data/Bills/BillHistory_Account1.csv", sep = "\t", row.names = FALSE) # 写入伪装成xls的HTML html_content <- ' <table id="tblMain"> <tr><th>UsageID</th><th>Usage</th><th>Date</th></tr> <tr><td>1</td><td>50</td><td>2024-01-01</td></tr> <tr><td>2</td><td>75</td><td>2024-01-02</td></tr> </table> ' writeLines(html_content, "data/Bills/BillHistory_2.xls") # 写入XLSX xlsx_data <- tibble(UsageID = 3:4, Usage = c(60, 80), Date = Sys.Date() - 2:1) write_xlsx(xlsx_data, "data/Usages/UsageHistory_4.xls.xlsx") # ---- 批量读取文件 ---- read_file_by_ext <- function(file_path) { if (grepl("\\.csv$", file_path)) { read.csv(file_path, sep = "\t") } else if (grepl("\\.xls$", file_path)) { readHTMLTable(file_path)$tblMain } else if (grepl("\\.xlsx$", file_path)) { read_excel(file_path) } else { stop("不支持的文件格式") } } files <- list.files(path = "data", recursive = TRUE, pattern = "\\.(csv|xls|xlsx)$", full.names = TRUE) df_list <- map(files, read_file_by_ext) names(df_list) <- basename(files) # 验证读取结果 lapply(df_list, head)
说明:该示例无需手动准备文件,运行后会自动创建测试目录和对应格式的模拟文件,最终输出与真实场景一致的读取结果,方便调试或他人复现。
内容的提问来源于stack exchange,提问作者nightstand
相关产品推荐
相关产品推荐

