簡體   English   中英

在 R 中填充矩陣的更快方法

[英]Faster way of filling a matrix in R

我想在 R 中填充一個矩陣,但每一列都必須有一個迭代的向量向下移動。 所以從某種意義上說,它將是一個下三角矩陣。 我的努力是這樣的:


x = c(3,4,8,9)
E <- matrix(0,length(x),length(x));E
for (i in 1:nrow(E)){
  E[i,1]=x[i]
}
E
for (i in 2:nrow(E)){
  for (j in 2:ncol(E)) {
    E[i,2] =x[i-1] }  }
E
for (i in 3:nrow(E)){
  for (j in 3:ncol(E)) {
    E[i,3] =x[i-2] }  }
E
for (i in 4:nrow(E)){
  for (j in 4:ncol(E)) {
    E[i,4] =x[i-3] }  }
E

每次從向量中刪除一個元素。但是有沒有一種更快的方法可以用更少的 for 循環和向量的 n 長度而不是 4 來完成它,作為一般化?

對不起,我無法抗拒。 這是另一種基本方法:

x <- c(3,4,8,9)
n <- length(x)
E <- diag(rep(x[1], n))
j <- unlist(sapply(length(x):2, function(i) x[2:i]))
E[lower.tri(E)] <- j

添加到 Rui 的基准代碼中,我們得到:

基准

我認為如果您將此代碼添加到基准測試中會很有趣

TIC <- function(x) {
  E <- diag(x)
  E[lower.tri(E, TRUE)] <- x[sequence(rev(seq_along(x)))]
  E
}

這使

> TIC(x)
     [,1] [,2] [,3] [,4]
[1,]    3    0    0    0
[2,]    4    3    0    0
[3,]    8    4    3    0
[4,]    9    8    4    3

在此處輸入圖像描述

這是一個基本的 R 方式。

E <- diag(length(x))
apply(lower.tri(E, diag = TRUE), 2, function(i) {
  c(rep(0, nrow(E) - sum(i)), x)[seq_along(x)]
})
#     [,1] [,2] [,3] [,4]
#[1,]    3    0    0    0
#[2,]    4    3    0    0
#[3,]    8    4    3    0
#[4,]    9    8    4    3

性能測試

如果問題是關於更快的代碼,這里是基准。


這些函數是我的和Ben Bolker 的代碼。

Rui <- function(x){
  E <- diag(length(x))
  inx <- seq_along(x)
  apply(lower.tri(E, diag = TRUE), 2, function(i) {
    c(rep(0, nrow(E) - sum(i)), x)[inx]
  })
}

Ben <- function(x){
  E <- matrix(0, nrow=length(x), ncol=length(x))
  diag(E) <- x[1]
  for (i in 2:length(x)) {
    E[row(E)==col(E)+i-1] <- x[i]
  }
  E
}

使用 ggplot 增加向量大小和 plot 進行ggplot

library(microbenchmark)
library(ggplot2)

test_speed <- function(n){
  out <- lapply(1:n, function(i){
    x <- sample(10*i)
    mb <- microbenchmark(
      Rui = Rui(x),
      Ben = Ben(x)
    )
    mb <- aggregate(time ~ expr, mb, median)
    mb$size <- 10*i
    mb
  })
  out <- do.call(rbind, out)
  out
}

res <- test_speed(10)

ggplot(res, aes(size, time, color = expr)) +
  geom_line() +
  geom_point() +
  scale_y_continuous(trans = "log10")

在此處輸入圖像描述

這不是超級高效,但比您的解決方案更好。 (效率低下的是我們每次都在構造row() / col()矩陣並生成一個完整的邏輯矩陣,而不是做一些索引。)另一方面,它似乎幾乎是瞬時的length(x)==100 (當我們 go 到 1000 時有點慢)。

E <- matrix(0, nrow=length(x), ncol=length(x))
diag(E) <- x[1]
for (i in 2:length(x)) {
   E[row(E)==col(E)+i-1] <- x[i]
}

有人可能編寫了更有效的代碼(在 Rcpp 中?)來索引矩陣的子對角線/非對角線元素。

盡管它很慢,但這個(IMO)的優點是它更容易理解。 您還可以通過對行和列之間的關系提出不同的條件來將其調整為許多不同的模式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM