I am trying to combine several for loops into a single loop or function. Each loop is evaluating if an individual is present at a site that is protected, and based on that is assigning a number (numbers represent sites) at each time step. After that, the results for each time step are stored in a matrix and later used in other analysis. The problem that I am having is that I am repeating the same loop several times to evaluate the different scenarios (10%, 50%, 100% of sites protected). Since I need to store my results for each scenario I can't think of a better way to simplify this into a single loop or function. Any ideas or suggestions will be appreciated. This is a very small and simplify idea of the problem. I would like to keep the structure of the loop since my original loop is using several if statements. The only thing that is changing is the proportion of sites that are protected.

N<-10 # number of sites
sites<-factor(seq(from=1,to=N))

sites10<-as.factor(sample(sites,N*1))     
sites5<-as.factor(sample(sites,N*0.5)) 
sites1<-as.factor(sample(sites,N*0.1)) 

steps<-10
P.stay<-0.9

# storing results

result<-matrix(0,nrow=steps) 
time.step<-seq(1,steps)
time.step<-data.frame(time.step)
time.step$event<-0

j<-numeric(steps)
j[1]<-sample(1:N,1)
time.step$event[1]<-j[1] 

for(i in 1:(steps-1)){

    if(j[i] %in% sites1){   

      if(rbinom(1,1,P.stay)==1){time.step$event[i+1]<-j[i+1]<-j[i]} else 

  time.step$event[i+1]<-0

  }

    time.step$event[i+1]<-j[i+1]<-sample(1:N,1)

}   

results.sites1<-as.factor(result)

###

result<-matrix(0,nrow=steps) 
time.step<-seq(1,steps)
time.step<-data.frame(time.step)
time.step$event<-0

j<-numeric(steps)
j[1]<-sample(1:N,1)
time.step$event[1]<-j[1] 

for(i in 1:(steps-1)){

  if(j[i] %in% sites5){   

    if(rbinom(1,1,P.stay)==1){time.step$event[i+1]<-j[i+1]<-j[i]} else 

      time.step$event[i+1]<-0

  }

  time.step$event[i+1]<-j[i+1]<-sample(1:N,1)

}   

results.sites5<-as.factor(result)

###

result<-matrix(0,nrow=steps) 
time.step<-seq(1,steps)
time.step<-data.frame(time.step)
time.step$event<-0

j<-numeric(steps)
j[1]<-sample(1:N,1)
time.step$event[1]<-j[1] 

for(i in 1:(steps-1)){

  if(j[i] %in% sites10){   

    if(rbinom(1,1,P.stay)==1){time.step$event[i+1]<-j[i+1]<-j[i]} else 

      time.step$event[i+1]<-0

  }

  time.step$event[i+1]<-j[i+1]<-sample(1:N,1)

}   

results.sites10<-as.factor(result)

#

results.sites1
results.sites5
results.sites10
有帮助吗?

解决方案

Instead of doing this:

sites10<-as.factor(sample(sites,N*1))     
sites5<-as.factor(sample(sites,N*0.5)) 
sites1<-as.factor(sample(sites,N*0.1)) 

and running distinct loops for each of the three variables, you can make a general loop and put it in a function, then use one of the -apply functions to call it with specific parameters. For example:

N<-10 # number of sites
sites<-factor(seq(from=1,to=N))
steps<-10
P.stay<-0.9

simulate.n.sites <- function(n) {
  n.sites <- sample(sites, n)

  result<-matrix(0,nrow=steps) 
  time.step<-seq(1,steps)
  time.step<-data.frame(time.step)
  time.step$event<-0

  j<-numeric(steps)
  j[1]<-sample(1:N,1)
  time.step$event[1]<-j[1] 

  for(i in 1:(steps-1)){

    if(j[i] %in% n.sites){ 

  ...etc...

  return(result)

}

results <- lapply(c(1, 5, 10), simulate.n.sites)

Now results will be a list, with three matrix elements.

The key is to identify places where you repeat yourself, and then refactor those areas into functions. Not only is this more concise, but it's easy to extend in the future. Want to sample for 2 site? Put a 2 in the vector you pass to lapply.

If you're unfamiliar with the -apply family of functions, definitely look into those.

I also suspect that much of the rest of your code could be simplified, but I think you've gutted it too much for me to make sense of it. For example, you define an element of time.step$event based on a condition, but then you overwrite that element. Surely this isn't what the actual code does?

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top