I fitted a poisson and negative binomial GLM on count data (=larva) and try to explain it as a function of a factor (=modality). However, as the traps used to trap larvae from inflorescences were exposed to different number of inflorescences, I than added an offset (=inflo) to the models for count normalization (in this case I am modeling the number of larvae per inflorescence).
I used the following data:
mydata <- data.frame(
modality = c("ER","ER","ER","ER","ER","ER","ER","ER","ER","ER","ER","ER","ER","ER","EH","EH","EH","EH","EH","EH","EH","EH","EH","EH","EH","EH","EH","EH","EH","EH","EH","EH","TS","TS","TS","TS","TS","TS","TS","TS","TS","TS","TS","TS","TS","TS"),
larva = c(149,184,51,35,10,6,102,29,151,37,57,95,44,38,2,245,29,22,30,32,124,42,17,49,39,36,60,14,73,22,16,21,21,54,53,39,41,58,47,42,12,1,4,2,3,1),
inflo = c(61,48,68,28,33,15,49,31,87,40,21,27,25,20,9,10,28,23,20,32,102,34,18,31,33,32,86,17,77,58,20,22,50,53,38,31,21,35,78,48,15,22,3,10,13,5)
) %>%
mutate(rate = larva / inflo)
Mean values per modality for count and rate data are :
mydata_stat <- mydata %>%
group_by(modality) %>%
summarise(mean_larva = mean(larva),
mean_inflo = mean(inflo),
mean_rate = mean(rate),
n = length(larva)
)
mydata_stat
# A tibble: 3 x 5
modality mean_larva mean_inflo mean_rate n
<chr> <dbl> <dbl> <dbl> <int>
1 EH 48.5 36.2 2.28 18
2 ER 70.6 39.5 1.75 14
3 TS 27 30.1 0.856 14
From what I understand, a count GLM models the conditional mean of counts. If μ is the mean response conditional on the level of modality and the log-link function is η = log(μ), then the model is:
η = β0 + β1 modalityER + β2 modalityTS, that is:
μ = exp(β0 + β1 modalityER + β2 modalityTS)
And for count GLM with an offset models the conditional mean of normalized counts. In this case, the model is:
η = β0 + β1 modalityER + β2 modalityTS + log(inflo), that is:
μ / inflo = exp(β0 + β1 modalityER + β2 modalityTS)
1/ Here the models and emmeans outputs for the Poisson and negative binomial GLMs without offset:
fit1 <- glm(larva ~ modality, family = "poisson", data = mydata)
emmeans(fit1, ~ modality, type="response")
modality rate SE df asymp.LCL asymp.UCL
EH 48.5 1.64 Inf 45.4 51.8
ER 70.6 2.25 Inf 66.3 75.1
TS 27.0 1.39 Inf 24.4 29.9
Confidence level used: 0.95
Intervals are back-transformed from the log scale
fit3 <- glm.nb(larva ~ modality, data = mydata)
emmeans(fit3, ~ modality, type="response")
modality response SE df asymp.LCL asymp.UCL
EH 48.5 10.59 Inf 31.6 74.4
ER 70.6 17.40 Inf 43.5 114.4
TS 27.0 6.75 Inf 16.5 44.1
Confidence level used: 0.95
Intervals are back-transformed from the log scale
I was expecting that the response means provided by emmeans was equal to observed means (=mean_larva in mydata_stat), which is the case for both models.
2/ Here the models and emmeans outputs for the Poisson and negative binomial GLMs with offset:
fit1_offset <- glm(larva ~ modality + offset(log(inflo)), family = "poisson", data = mydata)
emmeans(fit1_offset, ~ modality, type="response", offset = log(1))
modality rate SE df asymp.LCL asymp.UCL
EH 1.339 0.0453 Inf 1.25 1.431
ER 1.787 0.0568 Inf 1.68 1.902
TS 0.896 0.0461 Inf 0.81 0.991
fit3_offset <- glm.nb(larva ~ modality + offset(log(inflo)), data = mydata)
emmeans(fit3_offset, ~ modality, type="response", offset = log(1))
modality response SE df asymp.LCL asymp.UCL
EH 2.245 0.478 Inf 1.478 3.41
ER 1.755 0.424 Inf 1.093 2.82
TS 0.861 0.215 Inf 0.528 1.41
Confidence level used: 0.95
Intervals are back-transformed from the log scale
In the case of count GLMs with offset, I was also expecting that the response rates provided by emmeans was equal to observed rates (=mean_rate in mydata_stat), which is not the case.
In the case of the negative binomial GLM, it was close to mean_rate but not exactly the same, particularly for EH modality. And in the case of the Poisson GLM, it was instead exactly equal to mean_rate_2 = mean_larva / mean_inflo.
mydata_stat %>% mutate(mean_rate_2 = mean_larva / mean_inflo)
# A tibble: 3 x 6
modality mean_larva mean_inflo mean_rate n mean_rate_2
<chr> <dbl> <dbl> <dbl> <int> <dbl>
1 EH 48.5 36.2 2.28 18 1.34
2 ER 70.6 39.5 1.75 14 1.79
3 TS 27 30.1 0.856 14 0.896
I can't understand why...
I realized that there is a possible oulier in modality EH:
boxplot(rate ~ modality, data=mydata)
When removing the outlier, response rates provided by emmeans were much more closer between the two models and also closer the observed rates (=mean_rate in mydata_stat_cor - see below) :
mydata_cor <- mydata %>% filter(rate < 20)
mydata_stat_cor <- mydata_cor %>%
group_by(modality) %>%
summarise(mean_larva = mean(larva),
mean_inflo = mean(inflo),
mean_rate = mean(rate),
n = length(larva)
)
mydata_stat_cor %>% mutate(mean_rate_2 = mean_larva / mean_inflo)
# A tibble: 3 x 6
modality mean_larva mean_inflo mean_rate n mean_rate_2
<chr> <dbl> <dbl> <dbl> <int> <dbl>
1 EH 36.9 37.8 0.976 17 0.978
2 ER 70.6 39.5 1.75 14 1.79
3 TS 27 30.1 0.856 14 0.896
fit1_offset <- glm(larva ~ modality + offset(log(inflo)), family = "poisson", data = mydata_cor)
fit3_offset <- glm.nb(larva ~ modality + offset(log(inflo)), data = mydata_cor)
as.data.frame(emmeans(fit1_offset, ~ modality, type="response", offset = log(1)))$rate
[1] 0.9781931 1.7866184 0.8957346
as.data.frame(emmeans(fit3_offset, ~ modality, type="response", offset = log(1)))$response
[1] 0.9833245 1.7576010 0.8702802
Does it mans that mean_rates are managed differently in Poisson and Negative binomila GLMs? How can these differences in results be explained ? Thanks in advance for your helpful explanations.