【问题标题】:Can't coerce class of matrix numbers to integer不能将矩阵数字类强制为整数
【发布时间】:2012-09-01 19:47:54
【问题描述】:

我正在R 中写一个邻接矩阵,如下所示:

neighbours <- array(0, c(100,100))
for (i in 1:100) { neighbours[i,i] = 1 }    #reflexive

但后来我注意到class(neighbours)double matrix。这将占用更大的矩阵太多的空间。所以我想强制类型为integer,或者更好,因为这是无向的,logical

但是……

> class(neighbours[5])
[1] "numeric"
> class(neighbours[5]) <- "integer"
> class(neighbours[5])
[1] "numeric"

不听我的!

【问题讨论】:

  • 您可以使用diag(neighbours) &lt;- 1 避免for 循环。
  • 这将是另一个问题,您可以这样发布。

标签: r oop class matrix


【解决方案1】:

也许我遗漏了一些东西,但为什么不直接将它声明为一个逻辑数组呢?

neighbors <- array(FALSE, c(100,100))
diag(neighbors) <- TRUE

比较两者:

> object.size(array(0, c(100,100)))
80200 bytes
> object.size(array(FALSE, c(100,100)))
40200 bytes

编辑:我很想知道为什么逻辑数组每个条目占用 4B...

【讨论】:

  • 大概是因为逻辑是一个 32 位字。
  • 这是因为 R 在内部使用 C ints 存储整数和逻辑 SEXP。无论如何,使用逻辑数据类型在存储方面没有任何好处。请参阅 R 内部手册的relevant section
  • 有一个名为“bit”的包,它将逻辑向量存储为..等待它...位。
【解决方案2】:

一种选择是最初用整数 0 (0L) 填充,然后用整数 1 替换对角线 (1L)

m <- matrix(0L, 100, 100)
diag(m) <- 1L

这是在 R 中创建对角矩阵的更直接方法的一半:

m2 <- diag(1L, 100, 100)

> object.size(m)
40200 bytes
> object.size(m2)
80200 bytes

因此,分配整数矩阵m 然后更改对角线会得到最紧凑的密集矩阵。

【讨论】:

  • 这不是我说的吗?我认为m2 最终会与m 相同,但显然不是。
【解决方案3】:

Matrix 包(现在是标准包)中有一个 sparseMatrix 超类。如果你想要一个稀疏的对角矩阵,你可以用

创建它
library(Matrix) 
Matrix(diag(1,4) , sparse=TRUE)
#---------
4 x 4 sparse Matrix of class "dsCMatrix"

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

进一步的想法。如果您想将矩阵的模式更改为整数并且不关心它是否保持密集:

> m <- matrix(rnorm(25), 5)
> m[] <- as.integer(m)  
# you do need those square-brackets or the structure becomes a dimensionless vector.
> m
     [,1] [,2] [,3] [,4] [,5]
[1,]    0    0   -1    0    0
[2,]    1    0    0    0    0
[3,]    1    0    0    0    0
[4,]    0    0    0    0    0
[5,]    0    0    0   -1    0

Gavin 的评论引发了进一步的思考:如果您的目标是表示“邻接”,并且它是一个非常大的样本空间,您可能只想使用 sparseMatrix 类作为模型,而不是使用两列矩阵列中的对数.. 这并不是 sparseMatrices 保存它们的行、列和值的方式,但是 2 列存储模式可能适用于您的问题。请参阅“igraph”包中的工作示例。我认为您的问题可能表示为无向图。

【讨论】:

  • ... object.size(Matrix(diag(1, 100), sparse=TRUE)) 只有 2500 字节。
  • ...相对于密集的 80200 字节。非常好!
  • 这是一个很大的内存节省,但除非您想要使用该矩阵随后接受这些稀疏矩阵,否则一旦您需要转换为密集表示,保存将丢失。没有多少 CRAN 或基础 R 可以使用稀疏矩阵。
  • 也就是说,不能保证密集整数矩阵版本在经过一个或多个 R 函数后将保持整数。
  • 但是,如果 OP 研究 sparseMatrix 类的表示,他可能会深入了解他在提出无向邻接“矩阵”的更紧凑表示时所面临的问题。
【解决方案4】:

最好不要一开始就将其初始化为数字,但如果你不能这样做,请设置storage.mode

R> neighbours <- array(0, c(100,100))
R> for (i in 1:100) { neighbours[i,i] = 1 }
R> str(neighbours)
 num [1:100, 1:100] 1 0 0 0 0 0 0 0 0 0 ...
R> storage.mode(neighbours) <- "integer"
R> str(neighbours)
 int [1:100, 1:100] 1 0 0 0 0 0 0 0 0 0 ...
R> storage.mode(neighbours) <- "logical"
R> str(neighbours)
 logi [1:100, 1:100] TRUE FALSE FALSE FALSE FALSE FALSE ...

【讨论】:

    【解决方案5】:

    对于那些仍在寻找将现有数字矩阵强制为整数 1 的方法的人:

    m2 <- apply (m, c (1, 2), function (x) {
      (as.integer(x))
      })
    

    c(1, 2) 表示将函数应用于行和列。测试元素的类然后给出:

    > class(m2[1,])
    [1] "integer"
    > class(m[1,])
    [1] "numeric"
    > 
    

    我一直在寻找这样的东西,因为我需要转换一个已经存在的数字矩阵。这是计算速度非常慢的结果,因此修改代码比简单地转换结果要花费我更多的时间。

    【讨论】:

    • 这可能会更快,因为 m2 = apply(m, 2, as.integer)。请注意, m2 = apply(m, 1, as.integer) 将不起作用;令人气愤的是,R 转置了结果。
    猜你喜欢
    • 2016-08-24
    • 1970-01-01
    • 1970-01-01
    • 2020-09-08
    • 1970-01-01
    • 2021-11-25
    • 2021-12-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多