水平移动大矩阵的行

Sar*_*rah 1 r matrix

我正在寻找一种方法来水平移动方阵的行。特别是,我的问题是针对矩阵维度非常大的情况,比如 500*500 或 1000*1000,但我在这里举了一个 5*5 的小例子来说明这一点。假设我们有以下矩阵:

 1    2    3    4    5
 6    7    8    9   10
11   12   13   14   15
16   17   18   19   20
21   22   23   24   25
Run Code Online (Sandbox Code Playgroud)

我想水平移动我得到以下矩阵的行并用零填充空单元格:

1    7   13   19   25
2    8   14   20    0
3    9   15    0    0
4   10    0    0    0
5    0    0    0    0
Run Code Online (Sandbox Code Playgroud)

为像这样的小矩阵编写代码很容易R,但我正在寻找非常大的矩阵,正如我在上面指出的那样。任何帮助,将不胜感激。

whu*_*ber 5

该示例建议您创建一个新矩阵,其第 j是原始矩阵的第j,向左移动 j-1 个位置并在右侧填充零,如在此计算中使用 10,000 X 10,000 矩阵:

n <- 1e4
a <- matrix(seq_len(n^2), n, byrow=TRUE)
system.time({
  b <- matrix(sapply(seq_len(nrow(a)), function(i) c(a[i,i:ncol(a)], rep(0, i-1))), n, n)
})
Run Code Online (Sandbox Code Playgroud)
user  system elapsed 
0.97    0.00    0.99 
Run Code Online (Sandbox Code Playgroud)

(这是使用单个线程并反映了许多测试运行的典型运行。)对于具有 100,000,000 个条目的矩阵来说,一秒钟也不错。不过,这是一个很大的 RAM 猪,因此如果输入是稀疏矩阵,您可能需要修改代码,以便它也输出稀疏矩阵。


考虑到这一点,我c突然想到,假设可以极快地初始化零矩阵,那么避免串联并仅就地复制应该会更快。事实证明确实如此(而且代码更简单):

system.time({
  b <- matrix(0, nrow(a), ncol(a))
  for (i in seq_len(nrow(a))) b[1:(n+1-i), i] <- a[i, i:ncol(a)]
})
Run Code Online (Sandbox Code Playgroud)
user  system elapsed 
0.62    0.00    0.62 
Run Code Online (Sandbox Code Playgroud)

它快了大约 50%。由于循环开销相对较小并且循环体(大概)是优化的向量副本,因此不太可能存在明显更快的单线程解决方案。