Density, distribution function, quantile function and random generation for the Skellam distribution, the distribution of the difference of two independent Poisson variables (Skellam, 1946), with saddlepoint approximations, maximum likelihood estimation, and a regression model in which both rates depend on covariates. The distribution functions remain accurate for very large rates and far into the tails, on the natural and the log scale.
The Skellam distribution is the distribution of the difference of two independent Poisson counts: home goals minus away goals, up-ticks minus down-ticks, spikes in a stimulus window minus spikes in a baseline window. skellam provides its density, distribution function, quantile function and random generation, saddlepoint approximations, maximum likelihood estimation, and a regression model in which both rates depend on covariates.
The distribution functions are accurate to a relative error below 1e-12 for rates up
to at least 1e7, and remain finite on the log scale far into the tails, so they can be
used safely inside likelihoods. They follow the conventions of R's own dpois,
ppois, qpois and rpois.
Documentation, the changelog and the validation article are on the package website: https://monty-se.github.io/skellam/.
install.packages("skellam") # CRAN
# install.packages("remotes")
remotes::install_github("monty-se/skellam") # development version
library(skellam)
# X = Y1 - Y2 with Y1 ~ Poisson(12), Y2 ~ Poisson(8)
dskellam(-2:2, 12, 8) # P(X = x)
pskellam(0, 12, 8) # P(X <= 0)
qskellam(c(0.025, 0.975), 12, 8) # central 95% interval
set.seed(1)
rskellam(5, 12, 8) # random draws (integers)
# Log scale stays finite where the probability itself underflows
dskellam(500, 3, 2, log = TRUE)
pskellam(-1000, 3, 2, log.p = TRUE)
# Large rates
pskellam(0, 1e6, 1e6)
set.seed(1)
x <- rpois(2000, 12) - rpois(2000, 8)
skellam.mle(x)$param # close to (12, 8)
For y = Y1 - Y2, both rates follow a log-linear model in the covariates. param1
describes the rate of the counts that are added and param2 the rate of the counts
that are subtracted.
set.seed(123)
n <- 1000
covariate <- rnorm(n)
y <- rpois(n, exp(1 + 0.5 * covariate)) - rpois(n, exp(-0.5 + 0.3 * covariate))
fit <- skellam.reg(y, covariate)
fit$param1 # intercept ~ 1, slope ~ 0.5
fit$param2 # intercept ~ -0.5, slope ~ 0.3
Note for users of version 0.2.4 or earlier: in those versions
skellam.reg()returned the two parameter blocks the wrong way round (param1estimated the rate of the subtracted counts). Results obtained with them should be re-run. See NEWS for all changes.
If $Y_1 \sim \mathrm{Poisson}(\lambda_1)$ and $Y_2 \sim \mathrm{Poisson}(\lambda_2)$ are independent, $X = Y_1 - Y_2$ has probability mass function
$$ P(X = x) = e^{-(\lambda_1+\lambda_2)} \left(\frac{\lambda_1}{\lambda_2}\right)^{x/2} I_{|x|}\left(2\sqrt{\lambda_1\lambda_2}\right), \qquad x \in \mathbb{Z}, $$
where $I_\nu$ is the modified Bessel function of the first kind, with mean
$\lambda_1 - \lambda_2$ and variance $\lambda_1 + \lambda_2$. The help page
?skellam describes the numerical methods; the vignette
vignette("validate_skellam", package = "skellam") checks every function against
the definition.
Jerry W. Lewis, Patrick E. Brown and Michail Tsagris wrote the original package.
Montasser Ghachem (maintainer) and Oguz Ersan made the corrections and extensions
from version 0.2.5 on. Please report bugs at
https://github.com/monty-se/skellam/issues, and cite the package with
citation("skellam").
GPL (>= 2)