Occupancy modelling in R

Occupancy modelling in R from scratch: separating where a species lives from whether you saw it, with single-season, dynamic, multi-species and multi-scale models.

Presence-absence data almost never record absence. They record that nobody saw the species on the day they looked, which is a different thing, and the gap between the two is not noise you can average away. It is a downward bias on every occupancy figure, it gets worse with fewer visits, and it moves with anything that affects detection: observer, weather, season, habitat structure. If detection is correlated with the covariate you care about, the naive analysis does not just lose precision, it attenuates the slope you are trying to measure.

Occupancy models exist to take that apart. The idea is small: visit a site more than once inside a period when its status cannot change, and the pattern of detections and non-detections across visits carries enough information to estimate the probability of detection and the probability of occupancy separately. Everything else on this page is that idea with more structure bolted on.

This page collects every occupancy tutorial on this site. All of them build the likelihood by hand in base R, with optim or a hand-coded sampler, so you can see exactly which assumption is doing the work.

What you get, and what it costs

The basic model buys you an unbiased occupancy estimate at the price of repeat visits, and the price is real: a fixed budget spent on more visits is a budget not spent on more sites. That trade-off has an answer, and it depends on how detectable the species is, so it is worth working out before the field season rather than after.

The assumptions are where the interest is. Closure means the site cannot change status between visits within a season, and a species that comes and goes turns occupancy into “use”. Independence between visits fails as soon as one observer’s judgement carries across the day. Unmodelled detection heterogeneity is the recurring villain: it does not always announce itself in the fit, and several of the more ambitious variants read it as something else entirely. That is the honest limit worth stating plainly. Each extension buys another quantity from the same detection table, and each one rests on an assumption the table itself cannot test.

The variants, and what each one is for

Multiple seasons turn a static picture into colonisation and extinction, and stop naive year-to-year turnover from charging imperfect detection to local extinction. Multiple species let rare species borrow strength from common ones, and let you count the species nobody detected at all. Multiple scales separate whether the site is used from whether the species was available at the moment you sampled. Space matters when occupancy is spatially structured: a latent gradient inflates the significance of any covariate that shares its shape.

Two variants are more ambitious still: the Royle-Nichols model reads abundance out of bare detections, and a two-species model reads interaction out of co-occurrence. Both work. Both also have a slot where unmodelled heterogeneity or a shared gradient can arrive wearing the label you were hoping for.

The tutorials

Start here

Design, and the Bayesian version

More than one season

More than the basic model

More than one species

Scale and space

Where this connects

Newsletter

Get new tutorials by email

New R and QGIS tutorials for ecologists, straight to your inbox. No spam; unsubscribe anytime.

By subscribing you agree to receive these emails and confirm your address once. See the privacy policy.