8GB内存环境下用R无SQL读取多份大体积xlsx文件可行吗?
大体积XLSX文件的R处理方案咨询
环境与问题
- 硬件:9代i5处理器、8GB内存
- 文件:20份以上单工作表的200MB+ XLSX文件
- 现状:使用
readxl读取失败;Arrow仅支持CSV格式,目前手动转CSV后可正常处理,需实现批量转CSV脚本,同时想了解不借助SQL能否直接用R读取这类大XLSX文件
曾尝试的代码
1. 使用readxl读取XLSX(失败)
library(readxl) file.list <- list.files(pattern='*.xlsx') ha.list <- lapply(file.list, read_excel)
2. 转CSV后用Arrow处理(成功)
setwd('...') # 输入文件路径 library(tidyverse) library(magrittr) library(arrow) file.list <- list.files(pattern='*.csv') ds <- open_dataset(file.list, format = "csv") ds %>% glimpse
3. 拟写的批量转CSV脚本(未完善)
for (i in 1:length(file.list)) {a = openxlsx::readxlsx(file.list[i]) write.csv(a,'path') rm(a) }
解决方案
一、不借助SQL直接读取大XLSX文件
可以通过分块读取或优化读取参数解决内存不足问题:
1. 使用openxlsx分块读取
library(openxlsx) file_path <- "你的XLSX文件路径" chunk_size <- 10000 # 每次读取1万行,可根据内存调整 # 获取文件总行数 total_rows <- getSheetInfo(file_path)$rows # 逐块读取并处理 for (start_row in seq(1, total_rows, chunk_size)) { end_row <- min(start_row + chunk_size - 1, total_rows) chunk_data <- read.xlsx(file_path, startRow = start_row, rows = end_row - start_row + 1) # 在这里添加对chunk_data的处理逻辑(如分析、写入临时文件等) rm(chunk_data) gc() # 强制释放内存 }
2. 优化readxl读取参数
通过指定列类型、分块读取减少内存占用:
library(readxl) file_path <- "你的XLSX文件路径" chunk_size <- 10000 # 获取总行数 total_rows <- nrow(read_excel(file_path, n_max = 0)) # 逐块读取 for (start_row in seq(1, total_rows, chunk_size)) { end_row <- min(start_row + chunk_size - 1, total_rows) chunk_data <- read_excel( file_path, range = cell_rows(start_row:end_row), col_types = c("numeric", "text", "date") # 手动指定列类型,避免自动推断占用额外内存 ) # 处理chunk_data rm(chunk_data) gc() }
二、完善的批量转CSV脚本
修正原脚本语法错误,添加自动命名、内存释放逻辑,支持大文件分块写入:
方案1:直接读取后转CSV(适用于单文件内存可容纳的情况)
library(openxlsx) setwd("你的XLSX文件所在目录") xlsx_files <- list.files(pattern = "\\.xlsx$", ignore.case = TRUE) for (xlsx_file in xlsx_files) { # 读取XLSX文件 df <- read.xlsx(xlsx_file) # 生成对应CSV文件名 csv_file <- gsub("\\.xlsx$", ".csv", xlsx_file, ignore.case = TRUE) # 写入CSV(去掉行名减少文件体积) write.csv(df, csv_file, row.names = FALSE, fileEncoding = "UTF-8") # 释放内存 rm(df) gc() }
方案2:分块读取转CSV(适用于单文件内存无法容纳的情况)
library(openxlsx) setwd("你的XLSX文件所在目录") xlsx_files <- list.files(pattern = "\\.xlsx$", ignore.case = TRUE) chunk_size <- 10000 for (xlsx_file in xlsx_files) { csv_file <- gsub("\\.xlsx$", ".csv", xlsx_file, ignore.case = TRUE) total_rows <- getSheetInfo(xlsx_file)$rows # 先写入表头 header <- read.xlsx(xlsx_file, rows = 1) write.csv(header, csv_file, row.names = FALSE, fileEncoding = "UTF-8") rm(header) # 逐块读取并追加写入CSV for (start_row in seq(2, total_rows, chunk_size)) { end_row <- min(start_row + chunk_size - 1, total_rows) chunk_data <- read.xlsx(xlsx_file, startRow = start_row, rows = end_row - start_row + 1) write.table( chunk_data, csv_file, sep = ",", append = TRUE, row.names = FALSE, col.names = FALSE, fileEncoding = "UTF-8" ) rm(chunk_data) gc() } }
内容的提问来源于stack exchange,提问作者doraemon
相关产品推荐
相关产品推荐

