簡體   English   中英

如何對矩陣而不是向量使用sapply函數(或類似函數)?

[英]How to use sapply function (or similar) for a matrix, not a vector?

要加快以下速度:

x <- c(0, 1, 1.1, 1.5, 1.9, 2.8, 2.9, 3.5)
n <- length(x)
temp <- 0
  for(i in 1:n) {
    for(j in 1:n) {
      temp <- temp + dnorm(x[i] - x[j])
    }
  }

> temp
[1] 13.40157

我可以簡單地使用sapply函數,如下所示:

out <- sapply(x, function(a) dnorm(x - a)))
sum(out)

> sum(out)
[1] 13.40157

但是如何對matrix, not vector使用相同的技巧,那就是我需要加快以下步驟:

x <- matrix(c(3, 3.3, 5, 6, 7, 4), nrow=3, ncol=2, byrow=FALSE)
n <- length(x[,1])

library(mvtnorm) # for dmvnorm
temp <- 0
for(i in 1:n) {
  for(j in 1:n) {
    temp <- temp + dmvnorm(x[i,] - x[j,])
  }
}

> temp
[1] 0.6686979

在3x3的情況下,您需要根據以下幾對行計算密度:

1,1
1,2
1,3
2,1
2,2
2,3
3,1
3,2
3,3

我將通過生成一個矩陣,在該矩陣中每行對應每對中的第一個元素,在矩陣中每行對應每對中的第二個元素,將兩者相減,然后將結果傳遞給dmvnorm來解決dmvnorm

mat1 <- x[rep(1:n, each=n),]
mat2 <- x[rep(1:n, n),]
sum(dmvnorm(mat1-mat2))
# [1] 0.6686979

這似乎比使用循環的方法快很多:

library(mvtnorm)
OP <- function(x) {
  n <- nrow(x)  
  temp <- 0
  for(i in 1:n) {
    for(j in 1:n) {
      temp <- temp + dmvnorm(x[i,] - x[j,])
    }
  }
  return(temp)
}

josilber <- function(x) {
  n <- nrow(x)
  mat1 <- x[rep(1:n, each=n),]
  mat2 <- x[rep(1:n, n),]
  sum(dmvnorm(mat1-mat2))
}

# 100 x 10 matrix
set.seed(144)
x <- matrix(rnorm(1000), nrow=100)
all.equal(OP(x), josilber(x))
# [1] TRUE
library(microbenchmark)
microbenchmark(OP(x), josilber(x))
# Unit: milliseconds
#         expr        min        lq       mean     median         uq       max neval
#        OP(x) 654.553137 696.28275 738.655380 719.058485 760.699813 1194.5594   100
#  josilber(x)   2.775881   2.95865   6.789969   4.346013   5.948481   66.0617   100

對於此100 x 10的示例,使用矢量化方法的速度提高了100倍以上。

暫無
暫無

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

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