R中read_csv读取大数据集时停滞的原因及解决办法
问题分析与解决方案
为什么程序停滞?是内存不足吗?
是的,内存不足是核心原因。7.9GB内存面对200万行+1300列的数据集,哪怕只筛选部分变量,读取过程中的额外内存开销仍会直接耗尽资源:
- 多数CSV读取函数会先扫描全量文件推断列类型,这个阶段会占用大量临时内存;
- 即使指定
col_select,read_csv这类函数在类型推断环节仍会将全列数据加载到临时缓存,直到筛选完成才释放; - 原始数据集的内存占用远超7.9GB——哪怕每列仅占10KB,1300列的总数据量也会突破13GB,内存打满后系统会启用硬盘虚拟内存,读写速度骤降,表现为程序停滞。
解决方法
1. 精准控制列读取与类型指定
不要仅依赖col_select,提前手动指定列类型,避免自动推断带来的内存浪费:
# 针对所需变量定义类型,数值型用col_double,字符型用col_character,日期用col_date col_types <- cols_only( var_name1 = col_double(), var_name2 = col_character(), var_name3 = col_date(format = "%Y-%m-%d") # 将variables_to_use_2中的所有变量按此格式补充 ) my_data <- read_csv("G:/2005-2019_FinancialData_excl_D&GR_EDIT.csv", col_select = variables_to_use_2, col_types = col_types)
用fread的话,直接搭配select和colClasses,内存效率更高:
my_data <- fread("G:/2005-2019_FinancialData_excl_D&GR_EDIT.csv", select = variables_to_use_2, colClasses = c(var_name1 = "numeric", var_name2 = "character"))
2. 分块读取数据
若筛选后仍内存不足,将数据集拆分成小块分批读取处理:
chunk_size <- 100000 # 每次读取10万行 total_rows <- 2000000 chunks <- list() for (i in 0:(total_rows %/% chunk_size)) { skip_rows <- i * chunk_size # 处理最后一块可能不足chunk_size的情况 read_rows <- ifelse(skip_rows + chunk_size > total_rows, total_rows - skip_rows, chunk_size) chunk <- read_csv("G:/2005-2019_FinancialData_excl_D&GR_EDIT.csv", col_select = variables_to_use_2, col_types = col_types, skip = skip_rows, n_max = read_rows) chunks[[i+1]] <- chunk } # 若合并后内存足够,再合并所有块;否则直接在单块上处理分析 my_data <- bind_rows(chunks)
3. 优化内存占用
- 将重复值较多的字符型列转换为因子:
my_data$var_name2 <- as.factor(my_data$var_name2) - 使用更高效的数据结构:
data.table比普通data.frame内存占用更低,大文件处理性能更优;tibble也略优于原生data.frame。
4. 读取前清理内存
手动释放无用对象,腾出更多空间:
gc() # 强制垃圾回收 rm(list = ls()) # 清空当前环境所有对象,请提前保存需要保留的变量
5. 转换为高效二进制格式(可选)
若需频繁读取该文件,先将CSV转换为fst或feather二进制格式,后续读取速度和内存占用会大幅降低:
library(fst) # 成功读取一次后保存为fst write_fst(my_data, "G:/financial_data.fst") # 后续读取直接调用 my_data <- read_fst("G:/financial_data.fst", columns = variables_to_use_2)
内容的提问来源于stack exchange,提问作者Robin
相关产品推荐
相关产品推荐

