Извлечение элементов из вектора с использованием разреженной матрицы в R без преобразования в плотную матрицу - PullRequest
0 голосов
/ 23 января 2019

Я хотел бы извлечь все элементы из вектора x1, где i-й столбец существует в разреженной матрице. Мне нужно удалить все разреженные элементы, но результаты должны жить построчно в своем собственном объекте / списке / матрице.

Дано:

> x1
 [1]  1  2  3  4  5  6  7  8  9 10
> sparse_mat
8 x 10 sparse Matrix of class "ngCMatrix"

[1,] | | | . . . . . . .
[2,] . | | | . . . . . .
[3,] . . | | | . . . . .
[4,] . . . | | | . . . .
[5,] . . . . | | | . . .
[6,] . . . . . | | | . .
[7,] . . . . . . | | | .
[8,] . . . . . . . | | |

Желаемые результаты:

     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    2    3    4
[3,]    3    4    5
[4,]    4    5    6
[5,]    5    6    7
[6,]    6    7    8
[7,]    7    8    9
[8,]    8    9   10

Более полный пример с комментарием

library(Matrix)
library(purrr)

x1 <- 1:10

create_seq_sparse <- function(n, len) {
  bandSparse(m = n, n = n - len + 1L, k = seq_len(len) - 1L)
}

sparse_mat <- create_seq_sparse(10, 3)
sparse_mat
#> 8 x 10 sparse Matrix of class "ngCMatrix"
#>                         
#> [1,] | | | . . . . . . .
#> [2,] . | | | . . . . . .
#> [3,] . . | | | . . . . .
#> [4,] . . . | | | . . . .
#> [5,] . . . . | | | . . .
#> [6,] . . . . . | | | . .
#> [7,] . . . . . . | | | .
#> [8,] . . . . . . . | | |

# If there's a better way to do this, please advise?
mat_x1_mult_sparse <- t(t(sparse_mat) * x1) 
mat_x1_mult_sparse
#> 8 x 10 sparse Matrix of class "dgCMatrix"
#>                          
#> [1,] 1 2 3 . . . . . .  .
#> [2,] . 2 3 4 . . . . .  .
#> [3,] . . 3 4 5 . . . .  .
#> [4,] . . . 4 5 6 . . .  .
#> [5,] . . . . 5 6 7 . .  .
#> [6,] . . . . . 6 7 8 .  .
#> [7,] . . . . . . 7 8 9  .
#> [8,] . . . . . . . 8 9 10

# This is nice, but can't use in conjunction with keep?
# mat_x1_mult_sparse[1, , drop = FALSE] 

# Desired results, but this approach I think I lose the advantages of the sparse matrix?
mat_x1_mult_sparse[1, ] %>% keep(~ .x != 0)
#> [1] 1 2 3
mat_x1_mult_sparse[2, ] %>% keep(~ .x != 0)
#> [1] 2 3 4
# etc...
mat_x1_mult_sparse[8, ] %>% keep(~ .x != 0)
#> [1]  8  9 10

Ответы [ 2 ]

0 голосов
/ 25 февраля 2019

Стерли более ранний ответ, как только я заметил, что вы не хотите, чтобы ваша матрица была разреженной;Тем не менее, идея состоит в том, чтобы использовать слот i вашей матрицы:

# convert to dgCMatrix since ngCMatrix can only be on/off
out = as(sparse_mat, 'dgCMatrix')

# subset to the "on" elements of sparse_mat, 
#   and replace with the column number. The column number is
#   not stored directly so we have to make it ourselves, basically
#   by looking for when the value in @i stays the same or goes down
out[sparse_mat] = c(1L, cumsum(diff(sparse_mat@i) <= 0) + 1L)
out
# 8 x 10 sparse Matrix of class "dgCMatrix"
#                          
# [1,] 1 2 3 . . . . . .  .
# [2,] . 2 3 4 . . . . .  .
# [3,] . . 3 4 5 . . . .  .
# [4,] . . . 4 5 6 . . .  .
# [5,] . . . . 5 6 7 . .  .
# [6,] . . . . . 6 7 8 .  .
# [7,] . . . . . . 7 8 9  .
# [8,] . . . . . . . 8 9 10

Это должно быть чрезвычайно эффективным, так как метод [ для dgCMatrix должен быть разумным, а ваша замена - в точности желаемая длина (без потерь элементов).

0 голосов
/ 24 января 2019

Один из вариантов - использовать метод summary для получения индекса элементов, которые не редки

library(Matrix)
i1 <- summary(sparse_mat)
i2 <- as.matrix(i1[order(i1[,1]),]) # order by the row index
# multiply the sparse matrix by the replicated 'x1', extract elements
# with i2 index and convert it to n column matrix
matrix((sparse_mat * x1[col(sparse_mat)])[i2], ncol = 3, byrow = TRUE)
#.     [,1] [,2] [,3]
#[1,]    1    2    3
#[2,]    2    3    4
#[3,]    3    4    5
#[4,]    4    5    6
#[5,]    5    6    7
#[6,]    6    7    8
#[7,]    7    8    9
#[8,]    8    9   10
...