如何从稀疏向量创建对角矩阵

huangapple go评论65阅读模式
英文:

How to create a diagonal matrix from a sparse Vector

问题

假设 x 被定义为

x <- as(c(1,1,0,0,1,0), "sparseVector")

我想创建一个对角矩阵,其中对角元素由 x 中的条目给出。

我尝试过 Diagonal(x = x),但我收到以下错误。

Error in Diagonal(x = x) : 'x' has unsupported class "dsparseVector"
英文:

Suppose x is defined as

x &lt;- as(c(1,1,0,0,1,0), &quot;sparseVector&quot;)

I want to create a diagonal matrix where the diagonal elements are given by the entries in x.

I tried Diagonal(x = x), but I get the following error.

Error in Diagonal(x = x) : &#39;x&#39; has unsupported class &quot;dsparseVector&quot;

答案1

得分: 3

我认为你正在寻找 sparseMatrix。例如:

library(Matrix)

x <- c(1,1,0,0,1,0)
x <- sparseMatrix(i = seq(x), j = seq(x), x = x)
x
# 6 x 6 sparse Matrix of class "dgCMatrix"
#                 
# [1,] 1 . . . . .
# [2,] . 1 . . . .
# [3,] . . 0 . . .
# [4,] . . . 0 . .
# [5,] . . . . 1 .
# [6,] . . . . . 0

要将原始向量中的零视为稀疏元素:

x <- c(1,1,0,0,1,0)
x <- sparseMatrix(i = which(x!=0), j = which(x!=0), x = x[which(x!=0)], 
  dims = rep(length(x), 2))
x
# 6 x 6 sparse Matrix of class "dgCMatrix"
#                 
# [1,] 1 . . . . .
# [2,] . 1 . . . .
# [3,] . . . . . .
# [4,] . . . . . .
# [5,] . . . . 1 .
# [6,] . . . . . .
英文:

I think you are looking for sparseMatrix. e.g.:

library(Matrix)

x &lt;- c(1,1,0,0,1,0)
x &lt;- sparseMatrix(i = seq(x), j = seq(x), x = x)
x
# 6 x 6 sparse Matrix of class &quot;dgCMatrix&quot;
#                 
# [1,] 1 . . . . .
# [2,] . 1 . . . .
# [3,] . . 0 . . .
# [4,] . . . 0 . .
# [5,] . . . . 1 .
# [6,] . . . . . 0

To treat zeros in the original vector as sparse elements:

x &lt;- c(1,1,0,0,1,0)
x &lt;- sparseMatrix(i = which(x!=0), j = which(x!=0), x = x[which(x!=0)], 
  dims = rep(length(x), 2))
x
# 6 x 6 sparse Matrix of class &quot;dgCMatrix&quot;
#                 
# [1,] 1 . . . . .
# [2,] . 1 . . . .
# [3,] . . . . . .
# [4,] . . . . . .
# [5,] . . . . 1 .
# [6,] . . . . . .

答案2

得分: 3

您可以将“Diagonal”矩阵与您的稀疏向量相乘:

Diagonal(length(x)) * x
#6 x 6 sparse Matrix of class "dgCMatrix"
#                
#[1,] 1 . . . . .
#[2,] . 1 . . . .
#[3,] . . . . . .
#[4,] . . . . . .
#[5,] . . . . 1 .
#[6,] . . . . . .
英文:

You can multiply the Diagonal matrix with your sparse vector:

Diagonal(length(x)) * x
#6 x 6 sparse Matrix of class &quot;dgCMatrix&quot;
#                
#[1,] 1 . . . . .
#[2,] . 1 . . . .
#[3,] . . . . . .
#[4,] . . . . . .
#[5,] . . . . 1 .
#[6,] . . . . . .

答案3

得分: 2

可以使用sparseMatrix从x的组件构建它,创建一个dgCMatrix对象:

sparseMatrix(x@i, x@i, x = x@x, dims = c(x@length, x@length))

结果为:

6 x 6 稀疏矩阵,类别为 "dgCMatrix"

[1,] 1 . . . . .
[2,] . 1 . . . .
[3,] . . . . . .
[4,] . . . . . .
[5,] . . . . 1 .
[6,] . . . . . .

注意

library(Matrix)
x <- as(c(1, 1, 0, 0, 1, 0), "sparseVector")
英文:

It can be constructed from the components of x using sparseMatrix creating an object of dgCMatrix:

sparseMatrix(x@i, x@i, x = x@x, dims = c(x@length, x@length))

giving:

6 x 6 sparse Matrix of class &quot;dgCMatrix&quot;
                
[1,] 1 . . . . .
[2,] . 1 . . . .
[3,] . . . . . .
[4,] . . . . . .
[5,] . . . . 1 .
[6,] . . . . . .

Note

library(Matrix)
x &lt;- as(c(1, 1, 0, 0, 1, 0), &quot;sparseVector&quot;)

答案4

得分: 0

你想要 Diagonal(x = as.vector(&lt;sparseVector&gt;))。话虽如此,可以合理地期望 Diagonal(x = &lt;sparseVector&gt;) 做相同的事情。也许这是对 Matrix 1.6-1 的功能请求...

无论如何,结果将是一个继承自 diagonalMatrix 并显式存储对角线上的零的对象。是的,这是"次优"的,但作为回报,您可以受益于高度优化的 diagonalMatrix 方法。

如果您只关心对象大小,为什么不保留 sparseVector 表示?

library(Matrix)
set.seed(0)
n &lt;- 1e+06L
x0 &lt;- sample(c(0, 1), size = n, replace = TRUE, prob = c(1000, 1))
x &lt;- as(x0, &quot;sparseVector&quot;)
l &lt;- list(x0 = x0, x = x,
          D = Diagonal(x = as.vector(x)),
          C = sparseMatrix(i = x@i, j = x@i, x = x@x, dims = rep.int(x@length, 2L),
                           triangular = TRUE, repr = &quot;C&quot;),
          R = sparseMatrix(i = x@i, j = x@i, x = x@x, dims = rep.int(x@length, 2L),
                           triangular = TRUE, repr = &quot;R&quot;),
          T = sparseMatrix(i = x@i, j = x@i, x = x@x, dims = rep.int(x@length, 2L), 
                           triangular = TRUE, repr = &quot;T&quot;))
cl &lt;- vapply(l, class, &quot;&quot;)
os &lt;- vapply(l, object.size, 0)
data.frame(class = cl, bytes = os, ratio = os/min(os))
           class   bytes      ratio
x0       numeric 8000048 651.894394
x  dsparseVector   12272   1.000000
D      ddiMatrix 8001240 651.991525
C      dtCMatrix 4013064 327.009778
R      dtRMatrix 4013064 327.009778
T      dtTMatrix   16816   1.370274
n. &lt;- as.double(n) # 避免在 rsparsematrix 中整数溢出... 修复
M &lt;- rsparsematrix(n., n., 1/n.)
with(l, microbenchmark::microbenchmark(D %*% M, C %*% M, R %*% M, T %*% M))
Unit: milliseconds
    expr       min        lq     mean    median       uq      max neval
 D %*% M  6.028189  6.502477  6.89017  6.680889  7.13894 10.35902   100
 C %*% M 20.564288 20.793950 21.03865 20.909795 21.07154 24.19648   100
 R %*% M 21.509297 21.793222 22.63789 22.000969 22.49524 63.59588   100
 T %*% M 22.943067 23.205651 24.18345 23.497592 24.09761 64.76713   100
英文:

You want Diagonal(x = as.vector(&lt;sparseVector&gt;)). Having said that, it is reasonable to expect Diagonal(x = &lt;sparseVector&gt;) to do the same thing. Maybe that is a feature request for Matrix 1.6-1 ...

In any case, the result will be an object inheriting from diagonalMatrix and storing zeros on the diagonal explicitly. Yes, that is "suboptimal", but, in exchange, you benefit from highly optimized methods for diagonalMatrix.

If you are only interested in object size, then why not keep the sparseVector representation?

library(Matrix)
set.seed(0)
n &lt;- 1e+06L
x0 &lt;- sample(c(0, 1), size = n, replace = TRUE, prob = c(1000, 1))
x &lt;- as(x0, &quot;sparseVector&quot;)
l &lt;- list(x0 = x0, x = x,
          D = Diagonal(x = as.vector(x)),
          C = sparseMatrix(i = x@i, j = x@i, x = x@x, dims = rep.int(x@length, 2L),
                           triangular = TRUE, repr = &quot;C&quot;),
          R = sparseMatrix(i = x@i, j = x@i, x = x@x, dims = rep.int(x@length, 2L),
                           triangular = TRUE, repr = &quot;R&quot;),
          T = sparseMatrix(i = x@i, j = x@i, x = x@x, dims = rep.int(x@length, 2L), 
                           triangular = TRUE, repr = &quot;T&quot;))
cl &lt;- vapply(l, class, &quot;&quot;)
os &lt;- vapply(l, object.size, 0)
data.frame(class = cl, bytes = os, ratio = os/min(os))
           class   bytes      ratio
x0       numeric 8000048 651.894394
x  dsparseVector   12272   1.000000
D      ddiMatrix 8001240 651.991525
C      dtCMatrix 4013064 327.009778
R      dtRMatrix 4013064 327.009778
T      dtTMatrix   16816   1.370274
n. &lt;- as.double(n) # avoid integer overflow in rsparsematrix ... FIXME
M &lt;- rsparsematrix(n., n., 1/n.)
with(l, microbenchmark::microbenchmark(D %*% M, C %*% M, R %*% M, T %*% M))
Unit: milliseconds
    expr       min        lq     mean    median       uq      max neval
 D %*% M  6.028189  6.502477  6.89017  6.680889  7.13894 10.35902   100
 C %*% M 20.564288 20.793950 21.03865 20.909795 21.07154 24.19648   100
 R %*% M 21.509297 21.793222 22.63789 22.000969 22.49524 63.59588   100
 T %*% M 22.943067 23.205651 24.18345 23.497592 24.09761 64.76713   100

huangapple
  • 本文由 发表于 2023年7月13日 18:12:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/76678245.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定