by jlaake » Wed Jan 27, 2010 7:10 pm
At the risk of turning the phidot forum into an R forum, below I'm posting a revision to Jim's single season occupancy model. But first let me say, I'm glad to see Jim jumping into R and I learned something from his posting. When I learned programming it was in FORTRAN probably like Jim did. In switching from something like FORTRAN to R it is often hard to adjust to vectorized operations in R. A few years ago I would have likely posted a similar solution that Jim did. As I've learned more about R I've learned to adopt vectorized thinking. This has a couple of advantages. First it tends to speed up the code although these days loops in R are appreciably faster than they used to be. But more importantly, it tends to make solutions more generalizable. I took Jim's lik function, changed the computation to use a vectorized form with a matrix of p's (sites by time) and a vector of Psi's (by site) and the code can now be used to solve any single season occupancy model with formula rather than just the specific p(.)Psi(.) model that Jim's would fit. I didn't have to create a DM by hand and I didn't use any concept of a PIM. That's because I created a dataframe containing a record for each site-occasion pairing. If MARK was written that way there would be no need for PIMS. To be honest, I've not used PRESENCE so I don't know if it has PIMS. PIMS and creating DMs by hand needs to go away. It was a functional concept at one point in time but we should be moving away from it. If some of you caught Evan's presentation of our talk at EURING, he mentioned this at the end. Anyhow, I'll stop my blathering. Below is the code with the same data and some added "habitat" data to make it interesting. To make this generally useful, you would have to write additional code to add variable names to estimates and have a summary etc. No need to do that because the R package unmarked should do that, although I've not used it to be sure.
a=c(0,0,0,1,1,
0,1,0,0,0,
0,1,0,0,0,
1,1,1,1,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
1,0,0,0,0,
0,0,1,1,1,
0,0,1,1,1,
1,0,0,1,1,
1,0,1,1,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,1,0,
0,0,0,1,0,
0,0,0,0,1,
0,0,0,0,1);
k=5
n=length(a)/k; dim(a)=c(k,n); b=t(a); eps=.0000000000000001;
occdata=data.frame(Site= rep(1:n,each=k),habitat=rep(c(rep("a",20),rep("b",19)),each=k),time=factor(rep(1:k,n)))
seen=as.numeric(rowSums(b)>0)
lik <- function(th) { # likelihood function - th=parameter vector
psi=plogis(DM.psi%*%th[1:ncol(DM.psi)])
p=matrix(plogis(DM.p%*%th[(ncol(DM.psi)+1):length(th)]),nrow=n,ncol=k,byrow=TRUE)
neg.loglik.occ=-sum(seen*(b*log(p)+(1-b)*log(1-p)))-sum(seen*log(psi))
neg.loglik.notocc=-sum((1-seen)*log(apply((1-p)^(1-b),1,prod)*psi+1-psi))
return(neg.loglik.occ+neg.loglik.notocc)
}
DM.p=model.matrix(~1,occdata)
DM.psi=model.matrix(~1,occdata[occdata$time==1,])
out.null <- nlm(lik,c(0.1,0.2),hessian=T,print.level=0)
DM.p=model.matrix(~time,occdata)
DM.psi=model.matrix(~habitat,occdata[occdata$time==1,])
out.time.hab <- nlm(lik,c(0.1,0,0.2,0,0,0,0),hessian=T,print.level=0)