2014-09-19 4 views
2

나는 R을 사용하여 두 가지 벡터의 값을 계산하고 다른 멋진 작업을하기 전에 함수를 작성하고 있습니다. 두 벡터는 R 및 B는, 다음의 합산에 의해 주어진다 :R 내부 함수의 합계

enter image description here

과 $ \ 베타 $ 상수 및가 전달되는 TS이다

$$ R(i)=\sum_{k=1}^{i-1}(t_i-t_k)e^{-\beta(t_i-t_k)} $$

함수 및는 이벤트 발생 시간입니다. 따라서 i- 번째 이벤트가 발생하면 (t_i) B(i)R(i)을 계산합니다.이 시간은 그 이전까지 발생한 모든 이벤트 발생 시간 t_k을 사용하여 완료됩니다.

나는 기본적으로 둘 사이의 유일한 차이점은 지수 전에 광장에도 불구하고 두 번 모든 계산이

r <- rep(0,length(t)) 
for(i in 2:length(t)) { 
    r[i] <- sum((t[i]-t[which(t<t[i])])*exp(beta*(t[i]-t[which(t<t[i])]))) 
} 
b <- rep(0,length(t)) 
for(i in 2:length(t)) { 
    b[i] <- sum(((t[i]-t[which(t<t[i])])^2)*exp(beta*(t[i]-t[which(t<t[i])]))) 
} 

보다 더 효율적으로 일을 마련하고 싶습니다. 어떤 아이디어? 감사!

+0

't'는 일반적으로 얼마나 큽니까? 너무 크지 않다면'for '루프 대신'outer'를 사용할 수 있습니다. – Roland

+1

@ Hack-R 그들은 단지't' 벡터의 예제를 제공하지 않았기 때문에 R은 당신이't' 함수를 부분 집합하기를 원한다고 생각합니다. – Roland

+0

어,이 루프는 추악합니다. 벡터화는 게임의 이름입니다 ... 당신은 열이 t_i와 t_k 인 데이터 프레임을 사용해야합니다. 그런 다음 차이를 계산합니다. 그런 다음 차이에 대해 ifelse를 사용하십시오. 이것은 루프없이 수행 될 수 있으며 즉시 계산되어야합니다. –

답변

1

입력 벡터의 크기 때문에 명시적인 루프를 사용하는 것보다 효과적 일 수 없습니다. 그렇지 않으면 너무 많은 메모리가 필요합니다. 하지만 분명히 하나의 루프 만 있으면 문제는 당황 스럽다.

library(doParallel) 

cl <- makeCluster(4) 
registerDoParallel(cl) 

fun_r <- function(t, beta) { 
    res <- foreach(i = seq_along(t)[-1], .combine = cbind) %dopar% { 
    d <- t[i] - t[seq_len(i - 1)] 
    c(sum(d^2 * exp(-beta * d)), 
     sum(d * exp(-beta * d))) 
    } 
    cbind(0, unname(res)) 
} 

set.seed(42) 
t <- sort(rnorm(1e4)) 

ttt <- fun_r(t, 0.5) 
ttt[,1:10] 
#  [,1]  [,2]  [,3]  [,4]  [,5]  [,6]  [,7]  [,8]  [,9]  [,10] 
#[1,] 0 0.3223427 0.3571912 0.5101723 0.5369059 0.6072245 0.6420904 0.6625009 0.7287196 0.8478711 
#[2,] 0 0.4800071 0.5391521 0.8341596 0.8901340 1.0569168 1.1455994 1.2034259 1.3972700 1.7177646 

library(microbenchmark) 
microbenchmark(fun_r(t, 0.5), times=5) 
#Unit: seconds 
#   expr  min  lq median  uq  max neval 
#fun_r(t, 0.5) 5.538867 5.558164 5.562138 5.567474 5.642002  5 

stopCluster(cl) 

이 여전히 너무 느린 경우, 당신은 Rcpp 그것을 구현하는 시도 할 수 있습니다 :

은이 문제에 대한 이해이다.

+0

와우, 나는 당신의 대답 ('seq_along','seq_len' 등) 덕분에 새로운 유용한 명령을 배웠고'foreach'는 매우 흥미로운 루프 구현 방법입니다. 감사! –

0

방정식을 올바르게 이해하면 t[i] - t[1:i-1]을 먼저 따로 계산하면 이후의 모든 계산에서이 값을 사용해야합니다.

t <- rnorm(10) 
i <- 10 
beta <- 1 

tdiffs <- t[i]-t[1:i-1] 
betaexp <- exp(-beta*tdiffs) 
B <- sum(tdiffs^2*betaexp) 
R <- sum(tdiffs*betaexp) 
+0

그건 내 해석이야. 그것이 그가 원했던 것이기를 바랍니다. –