2

私はRとそのすべての知恵に比較的慣れておらず、スクリプトをより効率的にしようとしています。ループを使用して、動物が異なるサイト間をどのように移動するかをシミュレートしています。私が抱えている問題は、サイトの数を増やしたり、初期パラメーターを変更したりすると (同じサイトに移動または滞在する固定確率に基づいて)、非常に複雑なループで終了することです。異なるパラメーターを使用していくつかの異なるシミュレーションを実行する必要がある場合は、さまざまな状況に適応できる、より効率的なループまたは関数を好みます。最初のループは初期確率に従って行列を埋め、2 番目のループは値のリストからの乱数 (この例では 10) に対して累積確率行列を比較し、その個人の運命 (留まるか行くか) を決定します。新しいサイトへ)

これが私のコードの簡略化です:

N<-4 # number of sites
sites<-LETTERS[seq(from=1,to=N)]

p.stay<-0.45
p.move<-0.4

move<-matrix(c(0),nrow=N,ncol=N,dimnames=list(c(sites),c(sites)))
from<-array(0,c(N,N),dimnames=list(c(sites),c(sites)))
to<-array(0,c(N,N),dimnames=list(c(sites),c(sites)))

# 固定確率で行列を埋める #

for(from in 1:N){
  for(to in 1:N){
     if(from==to){move[from,to]<-p.stay} else {move[from,to]<-p.move/(N-1)}
     }
 }

move
cumsum.move<-cumsum(data.frame(move))

steps<-100
result<-as.character("") # for storing results
rand<-sample(random,steps,replace=TRUE) 
time.step<-data.frame(rand)
colnames(time.step)<-c("time.step")
time.step$event<-""
to.r<-(rbind(sites))
j<-sample(1:N,1,replace=T) # first column to select (random number)
k<-sample(1:N,1,replace=T) # site selected after leaving and coming back

# 長いループの始まり #

for(i in 1:steps){
   if (time.step$time.step[i]<cumsum.move[1,j]){time.step$event[i]<-to.r[1]} else 
     if (time.step$time.step[i]<cumsum.move[2,j]){time.step$event[i]<-to.r[2]} else
        if (time.step$time.step[i]<cumsum.move[3,j]){time.step$event[i]<-to.r[3]} else
           if (time.step$time.step[i]<cumsum.move[4,j]){time.step$event[i]<-to.r[4]} else
              if (time.step$time.step[i]<(0.95)){time.step$event[i]<-NA} else
                 if (time.step$time.step[i]<1.0) break # break the loop             

 result[i]<-time.step$event[i]
 j<-which(to.r==result[i])
 if(length(j)==0){j<-k} # for individuals the leave and come back later

 }

 time.step

 result

このループは、一連のシミュレーションの後に結果をシミュレートして保存する、より大きなループの一部です。このループの効率を改善して、サイトの数を簡単に変更したり、ループの大幅な編集を繰り返したりせずに初期確率パラメーターを変更したりできるようにする方法についてのアイデアやコメントをいただければ幸いです。

4

1 に答える 1

0

コードの本質を捉えているかどうかはわかりませんが、これは for ループよりも高速です。これは、数千歩を超え始めるとすぐに有利になり始めました。「ランダム」を一様分布のサンプルに置き換えます ( runif())

system.time(
time.step$event <- sapply(
  time.step$time.step, 
  function(x) rownames(
    cumsum.move[which(cumsum.move[,j] > x),])[[1]]
  )
)

これが10,000歩の私の結果です。私はラップトップで作業しているので、for ループを使用した 100,000 は 1 分未満で計算されませんでしたが、sapply は 14 秒で計算しました。

> system.time(
+ time.step$event <- sapply(
+ time.step$time.step,
+ function(x) rownames(
+ cumsum.move[which(cumsum.move[,j] > x),])[[1]]
+ )
+ )
   user  system elapsed 
  1.384   0.000   1.387 
> head(time.step)
  time.step event
1 0.2787642     C
2 0.3098240     C
3 0.9079045     D
4 0.9904031     D
5 0.3754330     C
6 0.6984415     C
> system.time(
+ for(i in 1:steps){
+ if (time.step$time.step[i]<cumsum.move[1,j]){time.step$event[i]<-to.r[1]} else
+ if (time.step$time.step[i]<cumsum.move[2,j]){time.step$event[i]<-to.r[2]} else
+ if (time.step$time.step[i]<cumsum.move[3,j]){time.step$event[i]<-to.r[3]} else
+ if (time.step$time.step[i]<cumsum.move[4,j]){time.step$event[i]<-to.r[4]}
+ result[i]<-time.step$event[i]
+ }
+ )
   user  system elapsed 
  3.137   0.000   3.143 
> head(time.step)
  time.step event
1 0.2787642     C
2 0.3098240     C
3 0.9079045     D
4 0.9904031     D
5 0.3754330     C
6 0.6984415     C
于 2012-10-24T04:30:19.140 に答える