如何用R的arrow包内存外读取分列存储的大矩阵及替代方案
内存外读取按列拆分的超大矩阵(R实现)
一、使用arrow包实现内存外访问
针对arrow默认适配行拆分数据集的特点,我们可以通过添加行索引并按行索引合并的方式,构建虚拟的完整内存外数据集,从而实现任意元素的访问。
步骤与代码示例
- 加载依赖包
library(arrow) library(dplyr)
- 定义路径并创建带行索引的数据集列表
path <- paste0(getwd(), "/example/") file_paths <- list.files(path, full.names = TRUE) # 为每个列拆分文件添加行索引,构建arrow Dataset dataset_list <- lapply(file_paths, function(fp) { open_dataset(fp) %>% mutate(row_id = row_number()) %>% # 添加行号作为合并键 relocate(row_id) # 将行号列移到首位,方便后续合并 })
- 合并为完整的内存外数据集
# 初始化完整数据集为第一个文件的Dataset full_dataset <- dataset_list[[1]] # 依次将剩余数据集按行号内连接,实现列拼接 for (ds in dataset_list[-1]) { full_dataset <- full_dataset %>% inner_join(ds, by = "row_id") }
- 访问任意元素
full_dataset是内存外的arrow Dataset,仅当调用collect()时才会加载数据到内存。示例访问第3行的X5列:
# 方式1:筛选行号+选择列 full_dataset %>% filter(row_id == 3) %>% select(X5) %>% collect() # 方式2:直接切片+选择列 full_dataset %>% slice(3) %>% select(X5) %>% collect()
二、其他支持内存外读取的R包
1. bigmemory
专为大矩阵设计,支持磁盘-backed的内存外存储,可直接访问矩阵任意元素:
library(bigmemory) # 读取所有列文件到列表 col_data <- lapply(file_paths, read.csv) # 合并为普通矩阵(若内存不足,可直接写入磁盘-backed矩阵) full_mat <- do.call(cbind, col_data) # 创建磁盘存储的big.matrix对象 bm <- filebacked.big.matrix( nrow = nrow(full_mat), ncol = ncol(full_mat), backingfile = "big_matrix.bin" ) bm[] <- full_mat[] # 直接访问第3行第5列元素 bm[3, 5]
2. ff
提供ff矩阵和ffdf数据结构,支持内存外操作,适合超大数据集:
library(ff) # 读取每个列文件为ffdf对象 ff_list <- lapply(file_paths, read.csv.ffdf) # 横向合并所有ffdf为完整的内存外数据集 full_ffdf <- do.call(cbind, ff_list) # 访问第3行X5列元素 full_ffdf[3, "X5"]
3. disk.frame
基于data.table的磁盘分块存储方案,支持灵活的内存外数据操作:
library(disk.frame) # 初始化disk.frame环境 setup_disk.frame() # 将每个列文件转为disk.frame对象 df_list <- lapply(file_paths, function(fp) { csv_to_disk.frame(fp, outdir = tempfile()) }) # 横向合并所有disk.frame full_df <- cbind.disk.frame(df_list) # 访问第3行X5列元素 full_df[3, "X5", keep = TRUE] %>% collect()
内容的提问来源于stack exchange,提问作者mr.T
相关产品推荐
相关产品推荐

