Свернуть на больших разреженных матрицах - PullRequest
0 голосов
/ 13 июня 2019

Есть ли способ сделать свертку / свертку для вычисления суммы строк на матрице разреженной для окон фиксированной длины? Я работаю с dgTMatrix для удобства, но моя проблема не относится к этому классу. Например, рассмотрим генерацию 8 x 10 разреженной матрицы.

library(Matrix)
i <- c(1,3:8); j <- c(2,9,6:10); x <- 7 * (1:7)
A <- sparseMatrix(i, j, x = x, giveCsparse = FALSE)    

> A
8 x 10 sparse Matrix of class "dgTMatrix"

[1,] . 7 . . .  .  .  .  .  .
[2,] . . . . .  .  .  .  .  .
[3,] . . . . .  .  .  . 14  .
[4,] . . . . . 21  .  .  .  .
[5,] . . . . .  . 28  .  .  .
[6,] . . . . .  .  . 35  .  .
[7,] . . . . .  .  .  . 42  .
[8,] . . . . .  .  .  .  . 49

Без первого приведения к матрице (например, as.matrix ()), один наивный подход использует sapply для вычисления сумм строк по каждому window=2 столбцу, что приводит к 8 x 5 плотному матрица.

window = 2
starts = seq(1,dim(A)[2],by=window)
A_rollsum <- sapply(starts, function(x) Matrix::rowSums(A[, x:(x+window-1)]))

> A_rollsum
     [,1] [,2] [,3] [,4] [,5]
[1,]    7    0    0    0    0
[2,]    0    0    0    0    0
[3,]    0    0    0    0   14
[4,]    0    0   21    0    0
[5,]    0    0    0   28    0
[6,]    0    0    0   35    0
[7,]    0    0    0    0   42
[8,]    0    0    0    0   49

Это не эффективно для больших разреженных матриц.

1 Ответ

2 голосов
/ 13 июня 2019

1) rollapply работает столбец за столбцом, и, по-видимому, вы хотите, чтобы строка за строкой транспонировалась, используйте Rollapply, как показано, и транспонируйте обратно:

t(rollapply(t(as.matrix(A)), 2, by = 2, sum))

дает:

     [,1] [,2] [,3] [,4] [,5]
[1,]    7    0    0    0    0
[2,]    0    0    0    0    0
[3,]    0    0    0    0   14
[4,]    0    0   21    0    0
[5,]    0    0    0   28    0
[6,]    0    0    0   35    0
[7,]    0    0    0    0   42
[8,]    0    0    0    0   49

2) Выше используются плотные матрицы, но если вам действительно нужны разреженные матрицы, обратите внимание, что здесь rollapply является линейным оператором, поэтому мы можем вычислить его матрицу и затем использовать умножение разреженных матриц.

d <- rollapply(diag(10), 2, by = 2, sum)
A %*% t(d)

Старый

Вопрос был изменен. это ответ на оригинальный вопрос.

Попробуйте r1. Покажем, что оно равно r2.

r1 <- rollapply(rowSums(A), 3, c)
r2 <- rollapply(as.matrix(A), 3, rowSums, by.column = FALSE)
identical(r1, r2)
## [1] TRUE

r1 и, следовательно, r2 равно:

> r1
     [,1] [,2] [,3]
[1,]    7    0   14
[2,]    0   14   21
[3,]   14   21   28
[4,]   21   28   35
[5,]   28   35   42
[6,]   35   42   49
...