#r
Вопрос:
Я пытаюсь конвертировать файл RDS, содержащий разреженную матрицу (dgCMatrix) Я получил от коллеги в обычный текстовый CSV-файл. Я понимаю, что этот файл будет иметь размер во много гигабайт, не нужно меня предупреждать. Я пробовал использовать as.matrix, но получаю ошибку «проблема слишком велика». Как я могу этого избежать?
> write.csv(as.matrix(x), 'table.csv')
Loading required package: Matrix
Error in asMethod(object) :
Cholmod error 'problem too large' at file ../Core/cholmod_dense.c, line 105
Комментарии:
1. Каковы размеры матрицы,
dim(x)
?2. Это 50281×82151
3. Это примерно 30,8 ГБ памяти для плотной версии вашей матрицы. При
chunk = 100
строках по умолчанию за проход моей функции ниже потребуется 62,7 МБ плотной матрицы за проход, чтобы она могла работать.
Ответ №1:
Почему бы не обработать разреженную матрицу по частям? Приведенный ниже код — это способ сделать это.
library(Matrix)
write_sparse_csv <- function(x, file, ..., chunk = 100){
passes <- nrow(x) %/% chunk
remaining <- nrow(x) %% chunk
if(passes > 0){
inx <- seq_len(chunk)
y <- x[inx, , drop = FALSE]
y <- as.matrix(y)
write.table(y, file, append = FALSE, sep = ",", col.names = !is.null(colnames(x)), ...)
passes <- passes - 1L
for(i in seq_len(passes)){
inx <- inx chunk
y <- x[inx, , drop = FALSE]
y <- as.matrix(y)
write.table(y, file, append = TRUE, sep = ",", col.names = FALSE, ...)
}
if(remaining > 0){
inx <- inx remaining
y <- x[inx, , drop = FALSE]
y <- as.matrix(y)
write.table(y, file, append = TRUE, sep = ",", col.names = FALSE, ...)
}
} else if(remaining > 0){
inx <- seq_len(remaining)
y <- x[inx, , drop = FALSE]
y <- as.matrix(y)
write.table(y, file, append = FALSE, sep = ",", col.names = FALSE, ...)
}
}
set.seed(2021)
n <- 1e6
M <- Matrix(sample(c(rep(0, 9*n/10), seq_len(n/10))), ncol = 5e2, sparse = TRUE)
dim(M)
write_sparse_csv(M, "~/tmp/test.csv")