Community-level density estimate - Modelling options

26 views
Skip to first unread message

Pedro Eça

unread,
Aug 24, 2026, 11:49:29 AM (14 days ago) Aug 24
to distance-sampling
Hello!

I'm modelling a set of data that came from an environmental monitoring program, I say this because due project scale and budget I only have a few samples perteaining to a relatively reduced number of observations.

Basically, I'm analyzing bird-count data from two transects, one in the "control area" and the other in the "impact area". Each transect was visited four times at different seasons of the year. Distance was recorded as bellow 50m or between 50 and 300m.

Right of the bat: I know the design isn't perfect, I basically have only one replicate for each site, different observers, the transect follows a dirt path, etc.. Still, I would like to produce a density estimate for all observed species for output sake. My objective is providing density estimates for all species between impact and control site.

Ideally, I would fit a Species-specific detection function with 'ds' and then apply it to a subset of data for the control and the impact site, like in the savannah sparrow example but applied to multiple species. But because some species only have one or two observations, I can't fit species-specific detection functions. To circumvent this, I classified all species into levels of detectability (High; Medium; Low. Based on expert assessment) and then fitted a detection function using Detectability as a covariate using all data (impact and control sites, I assume detectability is equal in both places).  Then I used this Detectability-specific model in 'dht2' using a subset of the impact-data and the contol-data, supplied as flatfiles.

First, is this approach sound? I never formally learned this package, so I got here by studying examples and package documentation. I'm not too worried about model selecting yet, just checking the the design of the analysis makes sense

Second, I wanted to check that my variables are coded correctly: Sample.label is the transect ID (A or B); Effort is transect length times the number of visits; I'm not supplying Region.label because I'm not interested in site-specific detection functions; Size is the number of individuals detected at each sample; Distance has been binned (no problems here)

Thank you for your attention and sorry for the long and somewhat informal exposition,

Kind regards!

Pedro Eça

Tiago Marques

unread,
Aug 24, 2026, 12:43:32 PM (14 days ago) Aug 24
to Pedro Eça, distance-sampling
Hello Pedro, list,

(random: once upon a time I had a student at FCUL called Pedro Eça - is that you 🙂?)

I refer to transects AC and BC in the control area, and AI and BI in the impact area.

You can do all you are saying, but I point out several aspects that I am afraid question the usefulness of doing so:

  1. Fair enough to assume detectability is the same in both areas (unless say impact was shooting birds say, then they be harder to spot after shooting them say)
  2. Fair enough to use detectability classes
  3. With just two bands, there's very limited options for detectability. Maybe a HN model, that is it. Results will be quite sensitive to whether the true detection function is truly half-normal or not, which is not a good thing
  4. I assume this is a design-based estimate, and so to estimate variance you have at best a sample size of two. No one would trust a variance based on two observations, and it will explode in cases where you had a very different number of detections in transect Ax and Bx, and it will be untrustworthy small if you happen to have similar numbers just as a fluke 
  5. This leads to.... If you are making comparisons between impact and control, by species, and you assume detectability by species pooled across impact/control, the comparisons on density are equivalent to the comparisons on the observed counts. This suggests that you will have little to no power to detect differences, and that power will be non-existent for low density species. If you only have 1 or 2 detections of a given species, and only 2 transects, the answer is there are no significant differences between impact and control. Think about it, is (0,1) different from (2,0), or even (3,1) from (0,0). Not really, these would be relatively fair results to observe if the same data generating mechanism was in both control/impact sits, in other words, if there were no impact.

You can check it yourself. Below I pretend that the impact has a decrease of 80% of the birds (a Poisson mean of 1, vs 5 in the control). The power to detect that change is... (simulation below) 0.1 (not to mention that in almost half the cases, variance was 0; this will be less so if the true variability is over-dispersed, but still) - you have only a 10% chance of finding a (huge) effect/difference we know is real. This is really well below what I would consider reasonable. So... bottom-line, your goal of evaluating whether there is an impact at the species level is simply not possible to be realistically evaluated with a sample size of 2 - distance sampling or no distance sampling involved... And probably if you use the code to see what happens with larger samples sizes, you will not get much better. It is hard to find differences with sample sizes of 2. 

Sorry, happy to be overruled. Code used is below if you want to try and change it a bit (e.g. change real differences) 

Hope that this helps, even if it means that I don't think you can do what you probably set out to do. No omelets without eggs kind of thing... 

Cheers,

T


set.seed(1656)
n<- 10000
teststat <- numeric(10000)
for (i in 1:n){
  #mean 2
  control <- rpois(2,5)
  #mean 6
  impact <- rpois(2,1)
  # not the right test, as you would probably not use a t.test here
  #then again, what would you use with a sample size of 2 ;) 
  if(var(control)==0 | var(impact)==0) {teststat[i] <-NA} else{
  teststat[i] <- t.test(control,impact)$p.value}
}
# how many NA's because variance is exactly 0 - no (sensible) test possible.
teststatNA <- sum(is.na(teststat))
teststatNA # how many non NA's
teststatnotNA <- sum(!is.na(teststat))
# estimated power to detect a difference of 300% (mean 2 vs 6) 
teststatnotNA

sum(teststat<0.05,na.rm=TRUE)/teststatnotNA




From: distance...@googlegroups.com <distance...@googlegroups.com> on behalf of Pedro Eça <pedroalm...@gmail.com>
Sent: Monday, August 24, 2026 3:50 PM
To: distance-sampling <distance...@googlegroups.com>
Subject: [distance-sampling] Community-level density estimate - Modelling options
--
You received this message because you are subscribed to the Google Groups "distance-sampling" group.
To unsubscribe from this group and stop receiving emails from it, send an email to distance-sampl...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/distance-sampling/0524f2ce-615a-4fcc-ae44-65d801a0d389n%40googlegroups.com.

Pedro Eça

unread,
Aug 24, 2026, 1:55:17 PM (14 days ago) Aug 24
to distance-sampling
Olá professor! Sim, também tive um Tiago Marques como professor na FCUL :) (vou responder em inglês para o resto das pessoas na lista)

Actually I only have a transect I and a transect C, so I have less than two samples per site (though they are sampled four times per year). I know that this size is small but it would be interesting to see how species-specific density estimates (or groups of species) change over the year as more monitoring campaigns accumulate. In this case I'll be working with paired samples under a BACI approach. Study areas are small so no more than one transects can be made (we also have point counts but that's another story). But I agree that statistically this has many flaws, right now I'm just working with that we have but for the next time maybe these inputs will affect the monitoring design.

If anything I'm reassured that my workflow is ok, there are so many different parameters in each Distance function... The code runs OK, and it is very surprsing that for most species density estimates are very similar to the ones in the literature, but some Confidence Intervals are very weird due to low Degrees of Freedom, which leads to huge UCI:

Captura de ecrã 2026-08-24 183647.png

The next step is going to be some troubleshooting to figure out what's happening

Reply all
Reply to author
Forward
0 new messages