Я имею дело с большими матрицами порядка 10^8
столбцов и 10^3-10^4
строк. Поскольку эти матрицы состоят только из единиц и нулей (более 99% нулей), я думаю, что разреженная конструкция в пакете Matrix
уместна. Однако я не вижу способа сгенерировать случайную матрицу, как в примере ниже. Обратите внимание, что ненулевые записи определяются вероятностями столбецcol_prob
.
set.seed(1) #For reproducibility
ncols <- 20
nrows <- 10
col_prob <- runif (ncols,0.1,0.2)
rmat <- matrix(rbinom(nrows*ncols,1,col_prob),
ncol=ncols,byrow=T)
Конечно, я могу преобразовать rmat
в разреженную матрицу:
rmat_sparse <- Matrix(rmat, sparse=TRUE)
Однако я хотел бы создать разреженную матрицу за один шаг. Я не уверен, что функция Matrix::rsparsematrix
может это сделать.
Следующая функция сгенерирует разреженную матрицу нужного вам типа, манипулируя значениями пустого объекта dgCMatrix
. Он в основном создает строки rbinom
по одной и соответственно заполняет значения @i
и @p
.
library(Matrix)
randsparse <- function(nrows, ncols, col_prob) {
mat <- Matrix(0, nrows, ncols, sparse = TRUE) #blank matrix for template
i <- vector(mode = "list", length = ncols) #each element of i contains the '1' rows
p <- rep(0, ncols) #p will be cumsum no of 1s by column
for(r in 1:nrows){
row <- rbinom(ncols, 1, col_prob) #random row
p <- p + row #add to column identifier
if (any(row == 1)){
for (j in which(row == 1)){
i[[j]] <- c(i[[j]], r-1) #append row identifier
}
}
}
p <- c(0, cumsum(p)) #this is the format required
i <- unlist(i)
x <- rep(1, length(i))
mat@i <- as.integer(i)
mat@p <- as.integer(p)
mat@x <- x
return(mat)
}
set.seed(1)
randsparse(10, 20, runif (20, 0.1, 0.2))
10 x 20 sparse Matrix of class "dgCMatrix"
[1,] 1 . . . . . . . 1 . . . . . 1 . . . . .
[2,] . . . . . . . . . . . . . . . . . . . .
[3,] 1 . . . . . . . . . . . . . . 1 1 . . 1
[4,] . . . . . . . . . . . . . 1 . . . . . .
[5,] . . . 1 . . . . 1 . 1 . . . . . . . . .
[6,] 1 . . . . . . . . . . . . . 1 . . . 1 .
[7,] . . . . . . . . . . . . . . . . . . . .
[8,] . 1 . . 1 . . . . . . . 1 . . 1 . . . 1
[9,] . . 1 . . . . . 1 . . . . 1 . . . 1 . .
[10,] . . . . . . . . . . 1 . . 1 . . . 1 1 .
@ stats134711 Вполне возможно, я не тестировал его на таких размерах, но он, по крайней мере, не позволяет вам использовать память для матрицы 10 ^ 12 элементов в процессе! Если вам действительно нужна скорость, вам, возможно, придется прибегнуть к чему-то вроде Rcpp
.
Да, я думаю, что это единственный способ решить проблему памяти и скорости.
@ stats134711 Вы можете немного улучшить скорость, изменив приведенное выше, чтобы сгенерировать столбцы с использованием sample(c(0,1), replace=TRUE, probs=c(1-p,p))
, что, как я полагаю, может быть быстрее, чем rbinom
с переменными вероятностями. Вероятно, проще всего использовать описанную выше общую процедуру, а затем транспонировать ее в конце, т.е. return(t(mat))
Не будет ли это медленно для больших
nrows=10^4
иncols=10^8
?