![](/img/trans.png)
[英]how to use apply (or sapply) with columns of matrix or dataframe as function args
[英]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.