Skip to contents

Evaluates the nth derivative of the digamma function.

This is the equivalent of base::psigamma() and returns identical values for numeric input, except that it carries derivatives. Exact differentiation (deriv_method = "exact") propagates a tangent alongside each value, and deli_polygamma() recognizes a tangent-carrying argument and applies the analytic rule itself, the polygamma function of order n + 1. psigamma() hands its argument to compiled code without dispatching, and errors on such an argument. Use deli_polygamma() inside estimating equations and inside transforms passed to delta_method(), and psigamma() for ordinary numeric work.

The two take their arguments in opposite orders. deli_polygamma(n, x) takes the derivative order first, matching Python's scipy.special.polygamma(n, x); psigamma(x, deriv = n) takes it second. deli_polygamma(1, 3) is psigamma(3, deriv = 1), not psigamma(1, deriv = 3). A positional substitution between the two computes a different quantity and raises no error.

Usage

deli_polygamma(n, x)

Arguments

n

Integer order of the derivative of the digamma function.

x

Numeric value or vector.

Value

Numeric polygamma values.

Exact differentiation

deriv_method = "exact" is forward-mode automatic differentiation: it replaces each value with an object carrying both the value and its derivative. deli supports those objects through S3 methods: the Ops, Math, and Summary group generics, plus non-group methods such as [, %*%, t(), c(), and mean(). standard_normal_cdf(), standard_normal_pdf(), deli_polygamma(), and deli_digamma() recognize a tangent-carrying argument themselves and apply their own analytic rule. Support within the group generics is partial; see vignette("getting-started") for the operations deli differentiates.

plogis(), qlogis(), pnorm(), dnorm(), and psigamma() take none of these paths. Each hands its argument straight to compiled code through .Call() or .Internal() without dispatching, so the tangent reaches C code that requires a plain number. deli catches the resulting failure and raises its own error, naming the function that stopped the computation and the deli function to write in its place. The same applies to every other distribution function in stats, such as qnorm(), which is named in the error even though deli exports no counterpart for it.

Each deli utility below returns the same values as its base R counterpart for numeric input. What separates them is whether the counterpart survives exact mode:

deli functionbase R counterpartbase R under deriv_method = "exact"
inverse_logit()stats::plogis()errors
logit()stats::qlogis()errors
standard_normal_cdf()stats::pnorm()errors
standard_normal_pdf()stats::dnorm()errors
deli_polygamma()base::psigamma()errors
deli_digamma()base::digamma()works
identity_transform()base::identity()works

For the first five rows, use the deli function inside estimating equations and inside transforms passed to delta_method(), and the base R function everywhere else: simulating data, post-fit display, plain numeric work. For the last two rows the base R function is usable everywhere, because digamma() is a Math group member with a tangent rule and identity() passes its argument through untouched.

The polygamma row is the one place where the arguments do not line up. deli_polygamma(n, x) takes the derivative order first and psigamma(x, deriv = n) takes it second, so a positional substitution between the two computes a different quantity and raises no error.

See also

base::psigamma(), the base R equivalent for ordinary numeric work, which takes its arguments in the other order, and deli_digamma() for the order-zero case.

Examples

deli_polygamma(0, 1)
#> [1] -0.5772157
deli_polygamma(1, c(1, 2, 5))
#> [1] 1.6449341 0.6449341 0.2213230

# The same values as the base R counterpart, with the arguments swapped
all.equal(deli_polygamma(1, c(1, 2, 5)), psigamma(c(1, 2, 5), deriv = 1))
#> [1] TRUE

# A gamma GLM, whose last parameter is the log of the shape
m <- m_estimate(
  mpg ~ wt,
  data = mtcars,
  .ee = ee_glm,
  distribution = "gamma",
  link = "log",
  init = c(3, 0, 0)
)

# Variance of the trigamma function at the estimated shape. Writing
# `psigamma(exp(theta[3]), deriv = 1)` here instead would error, because
# exact differentiation hands the transform a tangent-carrying argument.
delta_method(
  m,
  transform = function(theta) deli_polygamma(1, exp(theta[3])),
  deriv_method = "exact"
)
#>              [,1]
#> [1,] 1.617489e-05