Fat-tailed dispersal kernels

R
dispersal
seed dispersal
population ecology
ecology tutorial
Thin-tailed and fat-tailed dispersal kernels fit the same seed distances yet disagree by orders of magnitude on long-distance dispersal. A comparison in R.
Author

Tidy Ecology

Published

2026-06-23

Modified

2026-10-14

Corrected 14 October 2026: the post said that when traps only reach a short way the kernel families are indistinguishable in the bulk; it now says that the bulk may still rule out the Gaussian but often cannot separate the other families.

Corrected 1 October 2026: the post called the distance density the form you fit to trap distances, and its data seed-trap data; a trap of fixed area samples the per-area density, so the ring factor belongs to distances recorded for every seed, which is what the post simulates and fits. It also said that the stretched-exponential tail is not heavy, when it decays more slowly than any exponential; that all four fitted families agree on the bulk of the data, when the Gaussian misfits the bulk here and only the other three agree there; and that a fatter tail was the resolution of Reid’s paradox, when it was the proposed one.

Most of a dispersal kernel is uninteresting. Seeds pile up near the source, and any sensible density captures that. The part that matters for how a population moves is the far tail: the rare seed that travels ten or a hundred times the median distance. Those events set how fast a range expands, how far genes flow between patches, and how quickly an invader colonises new ground. When trees were found to have tracked postglacial warming faster than a thin-tailed kernel could explain (Reid’s paradox), the proposed resolution was that the tail is fatter than a Gaussian, so a few long jumps do the work of many short ones.

So the tail is the whole point, and it is exactly the part the data pins down worst. This tutorial makes that concrete: fit several kernel families to the same seed rain, and watch families that agree on the bulk disagree by orders of magnitude on the tail.

Thin tails and fat tails

Four location kernels span the range from thin to fat. Written as distance densities \(k_D(r) = 2\pi r\,f(r)\) (the form you fit to distances recorded for every seed, see the previous tutorial):

  • Gaussian, \(k_D(r) \propto r\,e^{-(r/a)^2}\). The tail falls like \(e^{-r^2}\): the thinnest of the four, essentially no long-distance dispersal.
  • Exponential, \(k_D(r) \propto r\,e^{-r/a}\). Tail falls like \(e^{-r}\), still thin.
  • Exponential-power, \(k_D(r) \propto r\,e^{-(r/a)^c}\). With shape c < 1 the tail is a stretched exponential: it decays more slowly than any exponential, so by the usual definition it is already heavy, though it still falls faster than any power law.
  • 2Dt (a two-dimensional Student-t), \(k_D(r) \propto r\,(1 + r^2/a^2)^{-(p+1)}\). The tail falls like a power law, \(r^{-(2p+1)}\). This is a heavy tail: it decays polynomially, not exponentially, so very long jumps stay possible.
kd_gauss <- function(r, a)    (2 * r / a^2) * exp(-(r / a)^2)
kd_exp   <- function(r, a)    (r / a^2) * exp(-r / a)
kd_ep    <- function(r, a, c) (c * r / (a^2 * gamma(2 / c))) * exp(-(r / a)^c)
kd_2dt   <- function(r, a, p) (2 * p * r / a^2) * (1 + r^2 / a^2)^(-(p + 1))
# survival functions P(r > R)
S_gauss <- function(R, a)    exp(-(R / a)^2)
S_exp   <- function(R, a)    exp(-R / a) * (1 + R / a)
S_ep    <- function(R, a, c) pgamma((R / a)^c, shape = 2 / c, lower.tail = FALSE)
S_2dt   <- function(R, a, p) (1 + R^2 / a^2)^(-p)

Now simulate a seed rain from a fat-tailed truth (a 2Dt with a power-law tail) and fit all four families by maximum likelihood.

set.seed(202)
a_true <- 25; p_true <- 1.5; n <- 600
r <- a_true * sqrt((1 - runif(n))^(-1 / p_true) - 1)   # 2Dt distances, tail ~ r^-4

fit1 <- function(nll, lo, hi) exp(optimize(nll, c(lo, hi))$minimum)
a_g <- fit1(function(la) -sum(log(kd_gauss(r, exp(la)))), -5, 12)
a_e <- fit1(function(la) -sum(log(kd_exp(r, exp(la)))), -5, 12)
op  <- optim(c(log(median(r)), 0), function(v) -sum(log(kd_ep(r, exp(v[1]), exp(v[2])))), method = "BFGS")
a_p <- exp(op$par[1]); c_p <- exp(op$par[2])
ot  <- optim(c(log(median(r)), 0), function(v) -sum(log(kd_2dt(r, exp(v[1]), exp(v[2])))), method = "BFGS")
a_t <- exp(ot$par[1]); p_t <- exp(ot$par[2])

ll <- function(f) sum(log(f))
aic <- c(gauss = 2 * 1 - 2 * ll(kd_gauss(r, a_g)),
         exp   = 2 * 1 - 2 * ll(kd_exp(r, a_e)),
         `exp-power` = 2 * 2 - 2 * ll(kd_ep(r, a_p, c_p)),
         `2Dt` = 2 * 2 - 2 * ll(kd_2dt(r, a_t, p_t)))

The heavy-tailed families win clearly. The 2Dt recovers the truth (fitted p = 1.45, scale 25.8 m, against p = 1.5, scale 25 m). Its AIC is 5011, against 5020 for the exponential-power, 5036 for the exponential, and 5345 for the Gaussian. On this dataset you can see the fat tail: the observed 99th percentile is 127 m, far past anything a Gaussian with this bulk would allow.

A histogram of seed distances in this sample, out to about 170 metres. Green and blue curves follow the histogram including its long right tail; the grey curve drops off too quickly in the tail region, and the gold curve is hard to tell from the blue one beyond about 60 metres.
Figure 1: The observed distances against the four fitted densities, over the range the data actually cover. The heavy-tailed 2Dt and exponential-power track the histogram into the tail; the Gaussian visibly runs short, and on this linear scale the exponential is hard to tell from the exponential-power beyond about 60 m (the survival plot below separates their tails).

Where they part company

The bulk fit hides the disagreement, because the disagreement is in the tail. Compute the probability of a seed travelling further than a fixed distance under each fitted kernel.

tailP <- function(R) c(
  Gaussian = S_gauss(R, a_g), exponential = S_exp(R, a_e),
  `exp-power` = S_ep(R, a_p, c_p), `2Dt` = S_2dt(R, a_t, p_t))
p100 <- tailP(100); p200 <- tailP(200); p400 <- tailP(400)
ratio200 <- p200[["2Dt"]] / p200[["Gaussian"]]
max_obs <- max(r)

At 100 m, still inside the observed range (9 of the 600 seeds landed beyond it), the families are already spreading: the 2Dt puts 1.8 seeds in a hundred beyond that distance, the Gaussian only 0.0255. At 200 m the gap is a chasm: the 2Dt gives \(2.6 \times 10^{-3}\), the exponential-power \(9.0 \times 10^{-5}\), the exponential \(3.9 \times 10^{-6}\), and the Gaussian \(4.2 \times 10^{-15}\). The 2Dt and the Gaussian differ by a factor of 600 billion at that one distance. At 400 m the Gaussian gives \(3 \times 10^{-58}\), a number so small it means “never”, while the 2Dt still gives \(4 \times 10^{-4}\).

Four decreasing curves on a log y-axis from 1 down to 10 to the minus 16 against distance. The curves lie almost on top of each other out to about 60 metres and then fan out, spanning about eight orders of magnitude by 170 metres, where a dashed vertical line marks the furthest observed seed in this sample. Further right the 2Dt stays highest while the Gaussian plunges fastest and leaves the bottom of the axis at about 210 metres.
Figure 2: The survival probability P(distance > R) under each fitted kernel, on a logarithmic scale. On this scale the four curves look close over the bulk of the data (dashed line marks the furthest observed seed) and fan out by orders of magnitude further out.

The uncomfortable part

Two lessons sit on top of each other here. The first is that the kernel family is not a cosmetic choice: it is the long-distance-dispersal prediction. Fit a Gaussian and you have decided, before seeing any far seed, that long jumps do not happen. Fit a 2Dt and you have allowed them. The bulk of the data need not decide this for you. Here it does rule out the Gaussian, whose peak sits well to the right of the histogram’s, but the exponential, also thin-tailed, fits the bulk about as well as the 2Dt and parts from it by orders of magnitude in the tail.

The second is quieter. The furthest seed in this sample landed at 171 m, and even the 2Dt, which here recovers the truth, reads its 400 m probability off the shape of a power law fitted mostly to seeds within 60 m. When the data do contain a fat tail, as here, you can at least tell a heavy family from a thin one. When they do not, which is the usual case with traps that only reach a short way, the bulk may still rule out the Gaussian but often cannot separate the other families, and the tail is a guess dressed as an estimate. The next tutorial follows the single quantity most exposed to this: the mean dispersal distance, which averages over the whole tail and can be infinite.

References

Clark JS 1998. American Naturalist 152(2):204-224 (10.1086/286162).

Clark JS, Silman M, Kern R, Macklin E, HilleRisLambers J 1999. Ecology 80(5):1475-1494 (10.1890/0012-9658(1999)080[1475:SDNAFP]2.0.CO;2).

Kot M, Lewis MA, van den Driessche P 1996. Ecology 77(7):2027-2042 (10.2307/2265698).

Nathan R 2006. Science 313(5788):786-788 (10.1126/science.1124975).

Newsletter

Get updates by email

An occasional email when tutorials are added or substantially corrected. No spam; unsubscribe anytime.

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