Реплицируйте индексы строк ненулевых записей в разреженной матрице по значениям этих записей - PullRequest
0 голосов
/ 05 июля 2018

Учитывая большую разреженную матрицу целых чисел, я хотел бы иметь список, в котором каждый элемент списка является вектором, содержащим индексы ненулевых элементов в соответствующей строке, , реплицированные по указанному количеству раз по элементу . Матрица большая, поэтому мне нужно масштабируемое решение.

Вот пример с очень медленным рабочим кодом.

sparse_matrix <- matrix(c(1, 0, 0, 0, 2, 0, 1, 5, 0, 0, 0, 0), nrow = 2)
#       [,1] [,2] [,3] [,4] [,5] [,6]
#[1,]    1    0    2    1    0    0
#[2,]    0    0    0    5    0    0


# A very slow attempt that gives the right answer
lapply(seq_len(nrow(sparse_matrix)), function(r) {
  rep(seq_len(ncol(sparse_matrix)), sparse_matrix[r,])
}     )

#[[1]]
#[1] 1 3 3 4
#
#[[2]]
#[1] 4 4 4 4 4

РЕДАКТИРОВАТЬ: Я понимаю, что я неправильно указал мой вопрос в оригинальном пост - извинения. Пожалуйста, обратитесь к приведенному выше примеру.

РЕДАКТИРОВАТЬ 2: Время двух решений для одного варианта использования:

sparse_matrix <- rsparsematrix (1E4,1E3, 0.01,rand.x = function(n) 1 + round(abs(rnorm(n))))
sparse_matrix <- as.matrix(sparse_matrix)

# 李哲源
ptm <- proc.time()
spM <- as(sparse_matrix, "dgRMatrix")
RowNumber <- rep(1:nrow(spM), diff(spM@p))
ColInd <- split(spM@j + 1, RowNumber)
nze <- split(spM@x, RowNumber)
output <- mapply(rep, ColInd, nze)  
print(proc.time() - ptm)
# 0.232 seconds

#akrun
ptm <- proc.time()
v1 <- c(col(sparse_matrix) * !! sparse_matrix)
v1 <-  setNames(v1, t(row(sparse_matrix)))
output <- rep(v1, sparse_matrix)
print(proc.time() - ptm)
# 1.8 seconds

Ответы [ 2 ]

0 голосов
/ 05 июля 2018

Вам знакомо сжатое хранилище строк для разреженной матрицы? Индекс, который вы хотите, является просто ключевым компонентом в таком хранилище. Пакет R Matrix имеет для этого свой класс "dgRMatrix".

library(Matrix)
spM <- as(sparse_matrix, "dgRMatrix")
## which row do those non-zero entries lie?
RowNumber <- rep(1:nrow(spM), diff(spM@p))
## position index of those entries on each row, i.e., column index
ColInd <- split(spM@j + 1, RowNumber)
## none-zero-element on each row
nze <- split(spM@x, RowNumber)
## expand position index by matrix value
mapply(rep, ColInd, nze)

#$`1`
#[1] 1 3 3 4

#$`2`
#[1] 4 4 4 4 4

Если матрица хранится как «dgCMatrix», можно ли ее преобразовать в «dgRMatrix»? В этом случае первая строка дает: нет метода или значения по умолчанию для приведения dgCMatrix к dgRMatrix

Это не метод принуждения от "dgCMatrix" к "dgRMatrix". sparse_matrix такая же плотная матрица, как и в вашем посте. Таким образом, принуждение за этим as от «матрицы» до «dgRMatrix».

Однако, если у вас уже есть это как "dgCMatrix", тогда вы можете сначала перенести его, а затем сделать что-то похожее на этом "dgCMatrix". Смотри ниже.

spM <- as(sparse_matrix, "dgCMatrix")
## transpose
spM <- t(spM)
## which column do those non-zero entries lie?
ColNumber <- rep(1:ncol(spM), diff(spM@p))
## position index of those entries on each column, i.e., row index
RowInd <- split(spM@i + 1, ColNumber)
## none-zero-element on each column
nze <- split(spM@x, ColNumber)
## expand position index by matrix value
mapply(rep, RowInd, nze)

#$`1`
#[1] 1 3 3 4

#$`2`
#[1] 4 4 4 4 4

Спасибо user20650 за его (большое) улучшение.

Для 1-го случая с "dgRMatrix",

spM <- as(sparse_matrix, "dgRMatrix")
RowNumber <- rep(1:nrow(spM), diff(spM@p))
split(rep(spM@j + 1, spM@x), rep(RowNumber, spM@x))

Для 2-го случая с "dgCMatrix"

spM <- as(sparse_matrix, "dgCMatrix")
ColInd <- rep(1:ncol(spM), diff(spM@p))
split(rep(ColInd, spM@x), rep(spM@i, spM@x))
0 голосов
/ 05 июля 2018

Мы можем использовать which с arr.ind как ИСТИНА, чтобы получить индекс строки и столбца в matrix

which(sparse_matrix !=0, arr.ind = TRUE) 

Для второго случая

rep(col(sparse_matrix) * !! sparse_matrix, sparse_matrix)

дает vector, но если нам нужен идентификатор, то создайте named vector

v1 <- c(col(sparse_matrix) * !! sparse_matrix)
v1 <-  setNames(v1, t(row(sparse_matrix)))
rep(v1, sparse_matrix)
#1 1 1 2 2 2 2 2 2 
#1 3 3 4 4 4 4 4 4 
...