Генерация случайной разреженной матрицы

Я имею дело с большими матрицами порядка 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 может это сделать.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
358
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Следующая функция сгенерирует разреженную матрицу нужного вам типа, манипулируя значениями пустого объекта 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 .

Не будет ли это медленно для больших nrows=10^4 и ncols=10^8?

stats134711 28.05.2019 21:42

@ stats134711 Вполне возможно, я не тестировал его на таких размерах, но он, по крайней мере, не позволяет вам использовать память для матрицы 10 ^ 12 элементов в процессе! Если вам действительно нужна скорость, вам, возможно, придется прибегнуть к чему-то вроде Rcpp.

Andrew Gustar 28.05.2019 21:45

Да, я думаю, что это единственный способ решить проблему памяти и скорости.

stats134711 28.05.2019 21:47

@ stats134711 Вы можете немного улучшить скорость, изменив приведенное выше, чтобы сгенерировать столбцы с использованием sample(c(0,1), replace=TRUE, probs=c(1-p,p)), что, как я полагаю, может быть быстрее, чем rbinom с переменными вероятностями. Вероятно, проще всего использовать описанную выше общую процедуру, а затем транспонировать ее в конце, т.е. return(t(mat))

Andrew Gustar 28.05.2019 21:55

Другие вопросы по теме