Вот подход с использованием умножения матриц, основанный на примере в 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
slam
пакет cran.r-project.org/web/packages/slam /slam.pdf - person s.brunel   schedule 25.06.2018