【问题标题】:How to calculate a large matrix of zeros and ones in R quickly and efficiently如何在 R 中快速有效地计算一个大的零和一矩阵
【发布时间】:2017-05-30 03:08:30
【问题描述】:

我使用 R 已经有一段时间了,但并不擅长优化我的代码以提高性能。

给定一个向量Y,长度为t,我正在尝试生成一个顺序为t 的方阵,以便它的ith 行对应于所有的$1_{Y_i j = 1, 2, ..., t。所以这是一个 0 / 1 二进制矩阵。

Y <- matrix(0, length(t), length(t))
for(i in 1:length(t))  Y[i, ] <- (t[i] <= t)

但是,我不认为这是最有效的方法,主要是看对象的大小。它与密集矩阵的大小相同,以字节为单位。我的目标是将其扩展到大t,但我相信这样一个矩阵的计算速度和存储空间将花费太长时间。有没有更快更有效的方法来存储和计算这个矩阵?

【问题讨论】:

  • 你没有在你的代码中定义t,所以你的代码不起作用,因为t是转置函数。
  • for 循环应该非常快,但您可以通过计算上三角或下三角来加快它:所以大约是计算/存储的一半。
  • 您正在尝试扩展您的自定义稀疏矩阵列表示。严格来说,我们不关心 t 的各个数值,只关心它们的相对排名:t = rank(t) 给出完全相同的输出。

标签: r matrix sparse-matrix


【解决方案1】:

如果我理解正确,我们可以使用:

outer(t, t, "<=") + 0L
## operator `"<="` returns TRUE / FALSE logical, 
## add an integer 0 to make a 0 / 1 binary integer matrix

让我们快速测试一下,与您的参考 for 循环进行比较。

set.seed(0); t <- runif(5)  ## reproducible data

outer(t, t, "<=") + 0L
#     [,1] [,2] [,3] [,4] [,5]
#[1,]    1    0    0    0    1
#[2,]    1    1    1    1    1
#[3,]    1    0    1    1    1
#[4,]    1    0    0    1    1
#[5,]    0    0    0    0    1

Y <- matrix(0, nrow=length(t), ncol=length(t))
for(i in 1:length(t)) {
  Y[i, ] <- t[i] <= t
}

Y
#     [,1] [,2] [,3] [,4] [,5]
#[1,]    1    0    0    0    1
#[2,]    1    1    1    1    1
#[3,]    1    0    1    1    1
#[4,]    1    0    0    1    1
#[5,]    0    0    0    0    1

我们得到相同的结果。宾果游戏!!


注意:

人们已阅读此答案的编辑历史。给出了一个带有sparseMatrix 的方法。我最初认为使用稀疏矩阵和列旋转会提高效率,但没有。基准测试显示outer 快了 6 倍或更多倍。因此,虽然我感到很伤心,但我不得不把我的大部分答案都扔掉。

【讨论】:

  • 我不认为如果矩阵实际上不是稀疏的,则使用稀疏矩阵会节省存储空间-(可能效率较低??)
  • 抱歉,我不确定我是否理解,“如果我们同时进行行和列旋转,我们最终会得到一个三角矩阵”是什么意思。 (但如果一半稀疏矩阵非零,那么我认为这可能比完整矩阵存储效率低)
  • 重新稀疏矩阵:如果一半为零,则并不意味着它的对象大小是大小的一半。试试object.size(f(t, FALSE)) ; object.size(f(t, TRUE))。另外,我发现 outer 的一个问题是,随着向量的长度增加超过循环,它可能会遇到内存问题。
  • 严格来说,我们不关心t 的各个数值,只关心它们的相对排名:t = rank(t) 给出完全相同的输出。对于此示例,它是 4 1 2 3 5。请注意,递增的子序列1 2 3 5 给出了一个上对角线的矩阵(至少是最右边的 4x4);这可能会被利用。但是你能选择一个不那么玩具的例子吗,比如长度为 12?并发布您的种子随机向量?
  • 具体来说,连续运行的1,2,3 可以替换为upper.tri() 个矩阵。我认为这可以被利用。
猜你喜欢
  • 2018-09-03
  • 1970-01-01
  • 2012-09-02
  • 1970-01-01
  • 2019-08-10
  • 2020-01-02
  • 2018-02-25
  • 1970-01-01
  • 2021-10-26
相关资源
最近更新 更多