You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于R中不同CSV读取函数内存占用差异的技术咨询

不同CSV读取函数的内存占用差异原因及优化建议

在R中使用base::read.csv()、readr::read_csv()、data.table::fread()和arrow::read_csv_arrow()读取同一个CSV文件时,发现生成的对象内存占用差异极大。具体测试代码及结果如下:

library(nycflights13)
library(readr)
library(data.table)
library(arrow)
library(dplyr)
library(lobstr)

# 导出测试数据
fl_original = nycflights13::flights
fwrite(fl_original, 'nycflights13_flights.csv')

# 用不同函数读取
fl_baseR = read.csv('nycflights13_flights.csv')
fl_readr = readr::read_csv('nycflights13_flights.csv')
fl_data.table = data.table::fread('nycflights13_flights.csv')
fl_arrow = arrow::read_csv_arrow('nycflights13_flights.csv')

# 查看内存占用
lobstr::obj_size(fl_baseR) # 33.12 MB
lobstr::obj_size(fl_readr) # 51.43 MB
lobstr::obj_size(fl_data.table) # 32.57 MB
lobstr::obj_size(fl_arrow) # 21.56 MB

# 查看对象类型
class(fl_baseR) # "data.frame"
class(fl_readr) # "spec_tbl_df" "tbl_df"      "tbl"         "data.frame" 
class(fl_data.table) # "data.table" "data.frame"
class(fl_arrow) # "tbl_df"     "tbl"        "data.frame"

可以看到arrow::read_csv_arrow()读取的数据内存仅为readr::read_csv()的~42%,尽管所有对象都包含data.frame类。以下是差异原因分析及读取建议:

内存差异的核心原因

1. 数据类型的精准选择与压缩

  • Arrow的类型优化:arrow::read_csv_arrow()默认会为数值列选择更紧凑的存储类型,比如用float32(单精度浮点数)代替R原生的double(双精度浮点数),用int32代替冗余的宽位整数类型,在保证数据精度足够的前提下大幅降低内存占用。而readr::read_csv()为避免数据溢出风险,默认采用更宽泛的数值类型,内存开销更大。
  • 字符列的编码优化:Arrow对重复率高的字符列会自动采用字典编码,进一步压缩内存体积;而readr默认以原生字符向量存储,无这类优化。

2. 对象结构与元数据开销

  • readr的元数据冗余:readr::read_csv()返回的spec_tbl_df对象会额外存储列类型推断的元数据(即spec属性),这部分信息会占用额外内存;而Arrow返回的tbl_df元数据更精简,仅保留必要的结构信息。
  • data.table的结构优化:data.table采用了更高效的内存布局,相比标准data.frame减少了部分对象属性的开销,因此内存占用略低于base R的read.csv()结果。

3. 底层内存管理机制

Arrow基于Apache Arrow的列存储格式,内存中数据的存储更连续、紧凑,避免了R原生数据结构(如向量)的额外内存开销;而readr、base R、data.table都是基于R的原生对象系统,每个向量都包含类型信息、长度等额外属性,累加起来会增加内存占用。

读取CSV的优化建议

  • 优先使用Arrow处理大型数据集:arrow::read_csv_arrow()内存效率最高,同时支持open_dataset()实现懒加载,无需一次性将全量数据加载到内存,适合超大型CSV文件。
  • 手动指定类型优化readr内存占用:如果需要兼容tidyverse生态,可以通过col_types参数手动设置更紧凑的类型,例如:
    fl_readr_optimized = readr::read_csv(
      'nycflights13_flights.csv',
      col_types = cols(
        dep_time = col_integer(),
        arr_time = col_integer(),
        dep_delay = col_float(),
        arr_delay = col_float()
      )
    )
    
  • data.table兼顾速度与内存:data.table::fread()读取速度快,内存效率接近base R,适合需要快速读取且内存要求不极致的场景,可通过colClasses参数指定类型进一步优化。
  • base R的优化方式:使用read.csv()时,通过指定colClasses参数明确列类型,避免自动推断带来的冗余,同时保持stringsAsFactors=FALSE减少不必要的因子转换开销。

内容的提问来源于stack exchange,提问作者Miao Cai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 16:57:34