[BACK]Return to extinction_risk_1.R CVS log [TXT][DIR] Up to [local] / ext

File: [local] / ext / extinction_risk_1.R (download)

Revision 1.4, Fri Jun 26 00:16:22 2015 JST (8 years, 10 months ago) by hako
Branch: MAIN
Changes since 1.3: +10 -6 lines

output format

# extinction_risk_1.R, ver. 1.6 2015/6/24
#
# Author: Hiroshi Hakoyama <hako@affrc.go.jp>
# Copyright (c) 2013-2015 Hiroshi Hakoyama <hako@affrc.go.jp>, All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY 
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
# AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Description:
# Estimates the demographic parameters and the probability of extinction within 
# a specific time period, t, from a time series of population size based on the 
# Wiener-drift process model (Dennis et al., 1991).
#
# Usage:
# ext1(dat, t = 100, ne = 1, verbose = FALSE)
#
# Arguments:
# dat		data.frame of 2 variables: Time and Population size
# t			a time period of interest
# ne		a lower (extinction) threshold of population size
# verbose	If set to FALSE, give the ML estimate of the probability of extinction
# within a specific time period t. If set to TRUE, give a more verbose output:
# the ML estimate of the growth rate (mu),
# the ML estimate of variance (s),
# the unbiased estimate of variance (us),
# the ML estimate of the probability attaining the threshold ne (psi),
# the ML estimate of the conditional mean time to reach the threshold, given 
# the threshold is reached (theta),
# the ML estimate of the conditional probability of extinction within a specific 
# time period t, given the threshold is reached (G),
# the ML estimate of the probability of extinction within a specific time period t (G*psi), and
# a lower 95 % confidence limit of parameter * (Low.CL.*), and
# a higher 95 % confidence limit of parameter * (High.CL.*)
# formatted	If set to TRUE, give the result by formatted output. If set to FALSE, give a list of estimates.
#
# References:
#  R. Lande and S. H. Orzack. Extinction dynamics of age-structured populations
# in a fluctuating environment. Proceedings of the National Academy of
# Sciences, 85(19):7418-7421, 1988.
# B. Dennis, P. L. Munholland, and J. M. Scott. Estimation of growth and
# extinction parameters for endangered species. Ecological Monographs, 
# 61:115-143, 1991.
#

ext1 <- function(dat, t = 100, ne = 1, alpha = 0.05, verbose = FALSE, formatted = TRUE) {
  yr <- ts(dat[, 1], start = c(dat[, 1][1])) # Year
  ps <- ts(dat[, 2], start = c(dat[, 1][1])) # Population size
  complete <- complete.cases(yr, ps)
  yr <- yr[complete]
  ps <- ps[complete]
  tau <- diff(yr) # time intervals, \tau_i = t_i - t_{i-1}
  w <- diff(log(ps)) # W_i = \log(N(t_i)/N(t_{i-1})) = X(t_i) - X(t_{i-1})
  q <- length(yr) - 1 # yr = \{t_0, t_1, \dots, t_q\}
  tq <- sum(tau)
  mu <- sum(w) / tq # ML estimate of growth rate
  s <- (1 / q) * sum((w - mu * tau)^2 / tau) # ML estimate of variance
  us <- q * s / (q - 1) # an unbiased estimate of variance
  xd <- log(ps[length(ps)] / ne)
  psi <- function(xd, mu, s) {
  	# The probability that the process will attain the threshold
    ifelse (mu <= 0, 1, exp(- 2 * mu * xd / s))
  }
  var.for.psi <- function(xd, mu, s) {
    ifelse (mu <= 0, 0, (4 * xd^2 / s) * (2 *(q -1) * mu^2 / (q^2 * s)))
  }
  Low.CL.psi <- function(xd, mu, s) {
    ifelse (mu <= 0, 1, exp(- (2 * mu * xd / s) - qnorm(1 - alpha / 2) * sqrt(var.for.psi(xd, mu, s))))
  }
  High.CL.psi <- function(xd, mu, s) {
    ifelse (mu <= 0, 1, exp(- (2 * mu * xd / s) + qnorm(1 - alpha / 2) * sqrt(var.for.psi(xd, mu, s))))
  }
  theta <- xd / abs(mu)
  Low.CL.mu  <- mu - qt(1 - alpha / 2, q - 1) * sqrt(us / tq)
  High.CL.mu <- mu + qt(1 - alpha / 2, q - 1) * sqrt(us / tq)
  Low.CL.s  <- q * s / qchisq(1 - alpha / 2, q - 1)
  High.CL.s <- q * s / qchisq(alpha / 2, q - 1)
  var.mu <- s / tq
  var.s  <- 2 * s^2 * (q - 1) / q^2
  erfc <- function (x) 2 * pnorm(-sqrt(2) * x)
  dGpsidmu <- - (xd / s) * 
    exp(- (2 * mu * xd) / s) * 
    erfc((- mu * t + xd) / sqrt(2 * s * t))
  dGpsids  <- (exp(- (mu * t + xd)^2 / (2 * s * t)) * t * xd) /
    (sqrt(2 * pi) * (s * t)^(3/2)) + 
    ((mu * xd) / s^2) * exp(- (2 * mu * xd) / s) *
    erfc((- mu * t + xd) / sqrt(2 * s * t))
  G <- function(t, xd, mu, s) {
  	# G = Pr[T <= t]: See Eq. (16) and Appendix of Dennis et al. (1991).
  	# Note that there is a typo in Eq. (16) of Dennis et al. (1991).
    a <- xd / sqrt(s)
    b <- abs(mu) / sqrt(s)
    y <- (b * t - a) / sqrt(t)
    z <- (b * t + a) / sqrt(t)
    d0 <-   0.2316419
    d1 <-   0.319381530
    d2 <- - 0.356563782
    d3 <-   1.781477937
    d4 <- - 1.821255978
    d5 <-   1.330274429
    qz <- 1 / (1 + d0 * z)
    g <- ifelse(z >= 4, pnorm(y) + dnorm(y) *
      (1 -
        (1 / z^2) +
        (1 * 3 / z^4) -
        (1 * 3 * 5 / z^6) +
        (1 * 3 * 5 * 7 / z^8) -
        (1 * 3 * 5 * 7 * 9 / z^10) +
        (1 * 3 * 5 * 7 * 9 * 11 / z^12) -
        (1 * 3 * 5 * 7 * 9 * 11 * 13 / z^14)
      ) / z,
      pnorm(y) +
      dnorm(y) * (d1 * qz + d2 * qz^2 + d3 * qz^3 + d4 * qz^4 + d5 * qz^5))
    gg <- pnorm((-xd + abs(mu) * t) / sqrt(s * t)) + exp(2 * xd * abs(mu) / s) *
          pnorm((-xd - abs(mu) * t) / sqrt(s * t))
    ifelse(is.nan(gg), g, gg)
  }
  H <- function(t, xd, mu, s) {
  	log(G(t, xd, mu, s) * psi(xd, mu, s) / (1 - G(t, xd, mu, s) * psi(xd, mu, s)))
  }
  Gpsi <- G(t, xd, mu, s) * psi(xd, mu, s)
  var.H <- var.mu * (dGpsidmu / (Gpsi * (1 - Gpsi)))^2 + 
           var.s  * (dGpsids  / (Gpsi * (1 - Gpsi)))^2
  hh <- H(t, xd, mu, s)
  Low.CL.Gpsi  <- 1 / (1 + exp(- hh + qnorm(1 - alpha / 2) * sqrt(var.H)))
  High.CL.Gpsi <- 1 / (1 + exp(- hh - qnorm(1 - alpha / 2) * sqrt(var.H)))
  if (verbose == TRUE) {
    results <- list(ne = ne, t = t, verbose = verbose,
      Growth.rate = mu,
      Low.CL.mu = Low.CL.mu,
      High.CL.mu = High.CL.mu,
      Variance = s, 
      Low.CL.s = Low.CL.s,
      High.CL.s = High.CL.s,
      Low.CL.psi = Low.CL.psi(xd, mu, s),
      High.CL.psi = High.CL.psi(xd, mu, s),
      Unbiased.variance = us, 
      Probability.attaining.the.threshold = psi(xd, mu, s), 
      Conditional.mean.extinction.time = theta, 
      Conditional.extinction.probability = G(t, xd, mu, s), 
      Extinction.probability = G(t, xd, mu, s) * psi(xd, mu, s),
      Low.CL.Gpsi = Low.CL.Gpsi,
      High.CL.Gpsi = High.CL.Gpsi)
    if (formatted == TRUE) {
      class(results) <- "ext1"
    }
    return(results)
  } else {
    results <- list(ne = ne, t = t, verbose = verbose, 
      Extinction.probability = G(t, xd, mu, s) * psi(xd, mu, s))
    if (formatted == TRUE) {
      class(results) <- "ext1"
    }
    return(results)
  }
}

print.ext1 <- function(obj, digits = 5) {
#  cat("\nExtinction risk\n")
  if (obj$verbose == TRUE) {
    output.est <- data.frame(
    c(formatC(obj$Growth.rate, digits = digits), 
      formatC(obj$Variance, digits = digits), 
      formatC(obj$Unbiased.variance, digits = digits),
      formatC(obj$Probability.attaining.the.threshold, digits = digits),
#      formatC(obj$Conditional.mean.extinction.time, digits = digits),
#      formatC(obj$Conditional.extinction.probability, digits = digits),
      formatC(obj$Extinction.probability, digits = digits)), 
    c(paste("(",formatC(obj$Low.CL.mu, digits = digits),", ", 
      formatC(obj$High.CL.mu, digits = digits),")", sep = ""), 
      paste("(",formatC(obj$Low.CL.s, digits = digits),", ", 
      formatC(obj$High.CL.s, digits = digits),")", sep = ""), 
      paste("(",formatC(obj$Low.CL.s, digits = digits),", ", 
      formatC(obj$High.CL.s, digits = digits),")", sep = ""),
      paste("(",formatC(obj$Low.CL.psi, digits = digits),", ", 
      formatC(obj$High.CL.psi, digits = digits),")", sep = ""),
#      "-",
      paste("(",formatC(obj$Low.CL.Gpsi, digits = digits),", ", 
      formatC(obj$High.CL.Gpsi, digits = digits),")", sep = "")))
    dimnames(output.est) <- list(
      c("Growth rate:",
        "Variance:",
        "Unbiased variance:",
        "Probability attaining the threshold:",
#        "Conditional mean extinction time:",
#        "Conditional extinction probability:",
        paste("Probability of decline to", obj$ne, "within", obj$t, "years:")),
      c("Estimate","95% confidence interval"))
    print(output.est)
  } else {
    output.est <- data.frame(
      c(formatC(obj$Extinction.probability, digits = digits)))
    dimnames(output.est) <- list(
      c(paste("Probability of decline to", obj$ne, "within", obj$t, "years:")),
      c("Estimate"))
  	print(output.est)
  }
}
#
# Examples
# Yellowstone grizzly bears (from Dennis et al., 1991)
 # dat <- data.frame(Year = c(1959, 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987), 
# Population = c(44, 47, 46, 44, 46, 45, 46, 40, 39, 39, 42, 44, 41, 40, 33, 36, 34, 39, 35, 34, 38, 36, 37, 41, 39, 51, 47, 57, 47))
# The probability of extinction (of decline to population size 1) within 100 years
# ext1(dat, 100)
# The probability of decline to 10 individuals within 100 years
# ext1(dat, 100, 10, verbose = TRUE)