Эквивалент функции rowum для класса Matrix (dgCMatrix)

Для базового класса матриц R у нас есть функция rowsum, которая очень быстро вычисляет суммы столбцов по группам строк.

Реализована ли эквивалентная функция или подход в Matrix-пакете?

Меня особенно интересует быстрая альтернатива rowsum для больших dgCMatrix-объектов (то есть миллионов строк, но примерно на 95% разреженных).


person Misconstruction    schedule 25.06.2018    source источник
comment
проверьте slam пакет cran.r-project.org/web/packages/slam /slam.pdf   -  person s.brunel    schedule 25.06.2018


Ответы (2)


Я знаю, что это старый вопрос, но Matrix::rowSums может быть той функцией, которую вы ищете.

person HowYaDoing    schedule 26.11.2018
comment
Matrix::rowSums() заменяет base::rowSums() (который вычисляет сумму каждой строки, возвращая вектор), а не base::rowsum() (который объединяет строки в указанных группах, возвращая матрицу с меньшим количеством строк) - person Mike M; 06.03.2021

Вот подход с использованием умножения матриц, основанный на примере в https://slowkow.com/notes/sparse-matrix/. Во-первых, давайте создадим разреженную матрицу для игры,

library(magrittr)
library(forcats)
library(stringr)
library(Matrix)

set.seed(42)
m <- sparseMatrix(
  i = sample(x = 1e4, size = 1e4),
  j = sample(x = 1e4, size = 1e4),
  x = rnorm(n = 1e4)
)
colnames(m) <- str_c("col", seq(ncol(m)))
rownames(m) <- str_c("row", seq(nrow(m)))

и вектор группировки, определяющий, какие строки суммировать,

group <- sample(1:10, nrow(m), replace = TRUE) %>%
  paste0("new_row", .) %>%
  fct_inorder

Является ли group фактором и порядок его уровней повлияет на окончательный порядок строк в объединенной матрице. Я сделал group коэффициент с уровнями, упорядоченными по первому появлению в group, чтобы порядок строк был похож на тот, который использовался в операции rowsum() с reorder = FALSE.

Затем мы создаем (разреженную) матрицу, которую мы можем умножить слева на m, чтобы получить версию m, строки которой были суммированы на основе group,

group_mat <- sparse.model.matrix(~ 0 + group) %>% t
# Adjust row names to get the correct final row names
rownames(group_mat) <- rownames(group_mat) %>% str_extract("(?<=^group).+")

msum <- group_mat %*% m  

Результат совпадает с base::rowsum() на плотной версии матрицы,

d <- as.matrix(m)
dsum <- rowsum(d, group, reorder = FALSE)
all.equal(as.matrix(msum), dsum)
#> [1] TRUE

но метод умножения разреженных матриц намного быстрее,

bench::mark( msum <- group_mat %*% m )$median
#> [1] 344µs
bench::mark( dsum <- rowsum(d, group) )$median
#> [1] 146ms
person Mike M    schedule 09.03.2021