2017-11-30 12 views
3

Rには、kxmの行列と文字列構造の行列をとり、各要素が三角形を定義する3xmの行列であるリストを返す関数mesh2listri()私は本当にこの機能をスピードアップしたいと思います。しかし、私はforループを回避する方法を理解することはできません。助けを前にありがとう。以下は、完全に再現可能な例です。メッシュからメッシュの三角形のリストを作成するための関数を高速化するR

mesh2listri <- function(mat, tri) { 
    if (ncol(tri) > 3) { 
    tri <- t(tri) 
    } 
    res <- NULL 
    for (i in 1:nrow(tri)) { 
    resi <- mat[tri[i, ], ] 
    res <- c(res, list(resi)) 
    print(i) 
    } 
    res 
} 

mat <- matrix(rnorm(90000, 0, 1), ncol = 3) 
tri <- matrix(sample(1:30000, replace = TRUE), ncol = 3) 
system.time(mesh2listri(mat, tri)) 

答えて

1

これは速いと思わ:3つの答えのための

mesh2listri_lap<-function(mat,tri){ 
if(ncol(tri)>3){tri<-t(tri)} 
res <- apply(tri, 1, function(x) mat[x,]) 
lapply(as.data.frame(res), function(x) matrix(x, nrow = 3, ncol = ncol(tri))) 
} 

新マイクロベンチマーク:

mat <- matrix(rnorm(6e6, 0, 1), ncol = 3) 
tri <- matrix(sample(3e5, replace = T), ncol = 3) 

b <- microbenchmark::microbenchmark(
    rez1 <- mesh2listri_lap(mat, tri), 
    rez2 <- mesh2listri_minem(mat, tri), 
    rez3 <- mesh2listri_prive(mat, tri),times = 10, unit = "s" 
) 
options(digits = 2) 
b 

> b 
Unit: seconds 
           expr min lq mean median uq max neval cld 
    rez1 <- mesh2listri_lap(mat, tri) 0.93 1.06 1.28 1.24 1.42 1.77 10 b 
rez2 <- mesh2listri_minem(mat, tri) 0.15 0.20 0.40 0.22 0.76 0.83 10 a 
rez3 <- mesh2listri_prive(mat, tri) 0.22 0.29 0.31 0.30 0.35 0.45 10 a 

グッドジョブ@minemと@F。 Privé!

+0

うわー!これはすごく速いです!どうもありがとう! –

+0

あなたは歓迎です:)私が言ったように、それが他のディメンションで動作するかどうかを確認するには、 'lapply()'コールで 'ncol'パラメータを変更する必要があります。 Embarassingly、私は行列代数ではうまくいきません... – LAP

2

少し速いです。

mesh2listri_byMinem <- function(mat, tri) { 
    if (ncol(tri) > 3) tri <- t(tri) 
    n <- nrow(tri) 
    l <- vector(mode = "list", length = n) 
    for (i in 1:n) { 
    resi <- mat[tri[i, ], ] 
    l[[i]] <- resi 
    } 
    l 
} 

# create larger data: 
mat <- matrix(rnorm(6e6, 0, 1), ncol = 3) 
tri <- matrix(sample(3e5, replace = T), ncol = 3) 

b <- microbenchmark::microbenchmark(
    rez1 <- mesh2listri_new(mat, tri), 
    rez2 <- mesh2listri_byMinem(mat, tri), times = 10, unit = "s" 
) 
options(digits = 2) 
b 
# Unit: seconds 
#         expr min lq mean median uq max neval cld 
#  rez1 <- mesh2listri_new(mat, tri) 0.630 0.85 0.94 0.85 0.92 1.86 10 b 
# rez2 <- mesh2listri_byMinem(mat, tri) 0.092 0.10 0.11 0.10 0.10 0.15 10 a 
+0

"少し"は控えめな表現です...素敵な仕事! – LAP

+0

どのような速度!再度、感謝します! –

2

だけ使用します。

mesh2listri <- function(mat, tri) { 
    if (ncol(tri) > 3) tri <- t(tri) 
    lapply(seq_len(nrow(tri)), function(i) mat[tri[i, ], ]) 
} 

あなたのコードに問題はあなたが各ステップで新しいベクトルを成長しているということです。

関連する問題