Checking a foraging analysis

ecology tutorial
R
foraging
model diagnostics
behaviour
Three checks for a foraging study in R: prey depletion in functional-response trials, telling type II from type III, and which currency the forager maximises.
Author

Tidy Ecology

Published

2026-07-30

Foraging theory makes sharp predictions, and sharp predictions are easy to test against data that were not collected to test them. Three checks catch the common ways a foraging analysis goes wrong: an estimate biased by the experiment itself, two models that the data cannot separate, and a prediction that depends on a choice the analyst never stated.

Check 1: did the prey deplete while you measured?

Holling’s disc equation assumes prey density is constant through a feeding trial. It is not: as the predator eats, prey run out, so the density it experiences falls below the density you set. Fit the disc equation to trial counts anyway and the attack rate comes out too low, because the model blames slow late-trial feeding on a low attack rate rather than on missing prey. Rogers 1972 The Journal of Animal Ecology 41(2):369-383 wrote down the random predator equation, which accounts for depletion, and it is solvable in base R with uniroot.

a0 <- 1.0; h0 <- 0.03                                   # the truth
rogers_Ne <- function(N0) uniroot(function(Ne)          # prey eaten with depletion
  Ne - N0*(1 - exp(-a0*(1 - h0*Ne))), c(0, N0 - 1e-9))$root
c(disc_attack_rate = unname(a_disc), rogers_attack_rate = unname(a_rog), true = a0)
  disc_attack_rate rogers_attack_rate               true 
         0.6647809          0.9105330          1.0000000 

Fitting the disc equation recovers an attack rate of 0.66, only 66 per cent of the true 1.0. The depletion-aware fit recovers 0.91, 91 per cent. The bias is not small and it is one-directional: any functional response fitted to trials where prey were not replaced will understate how fast the predator attacks. The check is to use the random predator equation, or to top prey up during the trial so density really is constant.

db <- data.frame(method = factor(c("true","disc equation","random predator"),
                                 levels = c("true","disc equation","random predator")),
                 a = c(a0, a_disc, a_rog))
ggplot(db, aes(method, a, fill = method)) +
  geom_col(width = 0.6) +
  geom_hline(yintercept = a0, colour = col_true, linetype = "dashed") +
  scale_fill_manual(values = c("true" = col_true, "disc equation" = col_disc, "random predator" = col_rog), guide = "none") +
  labs(x = NULL, y = "Estimated attack rate", title = "Depletion biases the disc-equation attack rate down")
Bar chart of attack rate: a true value, a much lower disc-equation estimate, and a random-predator estimate close to the truth.
Figure 1: Estimated attack rate from the two fits. The disc equation, ignoring that prey deplete during a trial, lands well below the truth; the random predator equation recovers it.

Check 2: can the data tell type II from type III?

The difference between type II and type III lives at low prey density, and so does the ability to tell them apart. The clean diagnostic is not intake but the proportion of prey eaten, intake divided by density. Under type II that proportion is highest at the lowest density and falls throughout. Under type III it rises to a hump and only then falls.

propII  <- function(N) 0.9/(1 + 0.9*0.045*N)             # Ne/N, type II
propIII <- function(N) 0.05*N/(1 + 0.05*0.045*N^2)       # Ne/N, type III
rbind(type_II  = round(propII(c(2, 20, 60)), 3),
      type_III = round(propIII(c(2, 20, 60)), 3))
          [,1]  [,2]  [,3]
type_II  0.833 0.497 0.262
type_III 0.099 0.526 0.330

At a density of 2 the two responses predict proportions of 0.83 and 0.10, a large gap; by a density of 60 they have converged. If your feeding trials start at moderate densities, both curves fit and the proportion-eaten plot cannot separate them, yet they imply opposite things for whether the predator can regulate its prey. The check is to sample the low-density end deliberately, and to plot proportion eaten, not intake, where the two models actually diverge.

dp <- rbind(data.frame(N = Ng, p = propII(Ng),  type = "type II"),
            data.frame(N = Ng, p = propIII(Ng), type = "type III"))
ggplot(dp, aes(N, p, colour = type)) +
  annotate("rect", xmin = 0, xmax = 15, ymin = -Inf, ymax = Inf, fill = "#8aa29e", alpha = 0.15) +
  geom_line(linewidth = 1) +
  scale_colour_manual(values = c("type II" = col_disc, "type III" = col_rog)) +
  labs(x = "Prey density", y = "Proportion of prey eaten", colour = NULL,
       title = "The two responses separate only where prey are scarce")
Two curves of proportion eaten against prey density; the ochre type II curve declines throughout, the green type III curve rises then declines, differing most at low density.
Figure 2: Proportion of prey eaten against density. Type II (ochre) falls from the start; type III (green) rises to a hump then falls. The models separate only at low density, shaded.

Check 3: which currency is the forager counting?

The marginal value theorem and the diet model both assume the forager maximises the long-run rate of energy intake. That is a choice, not a fact. An animal saving for a lean season may maximise net energy after paying its own foraging metabolism; one at risk of predation may minimise exposure time. Different currencies give different predictions from the same gain curve.

g <- function(t) 30*(1 - exp(-0.18*t)); gp <- function(t) 30*0.18*exp(-0.18*t)
t_rate <- uniroot(function(t) gp(t) - g(t)/(t + 6), c(1e-6, 200))$root      # maximise rate
tt <- seq(0.01, 60, 0.01)
t_eff  <- tt[which.max((g(tt) - 0.6*tt)/(tt + 6))]                          # net of metabolism
round(c(rate_currency = t_rate, net_energy_currency = t_eff), 2)
      rate_currency net_energy_currency 
               6.57                5.65 

A rate-maximiser leaves the patch at 6.6; a forager counting net energy after metabolism leaves at 5.6, a 14 per cent difference in predicted residence, with no change to the environment. When observed behaviour misses a rate-maximising prediction, the first question is not whether the theory is wrong but whether you guessed the currency (Pyke 1984 Annual Review of Ecology and Systematics 15(1):523-575). State the currency, and where you can, test more than one.

Deviations are data

Foraging theory is a set of predictions about an optimiser, and animals are not optimisers so much as satisficers working with partial information and real risk. That is why these models earn their keep even when animals depart from them: a clean prediction turns every departure into a measurement. A predator that eats a poor prey it should ignore is telling you about recognition error or nutrient needs; a forager that stays in a patch too long is telling you about uncertainty or safety. Run the three checks so the numbers are sound, then read the residuals as biology, not as failure.

References

  • Holling CS 1959. The Canadian Entomologist 91(7):385-398 (10.4039/Ent91385-7).
  • Pyke GH 1984. Annual Review of Ecology and Systematics 15(1):523-575 (10.1146/annurev.es.15.110184.002515).
  • Rogers D 1972. The Journal of Animal Ecology 41(2):369-383 (10.2307/3474).

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.