⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 distn.r

📁 使用R语言的马尔科夫链蒙特卡洛模拟(MCMC)源代码程序。
💻 R
字号:
########## Density Functions and Random Number Generators ############ note: Matthew Fasman has been working on replacing these with#       functions coded in C++.  These have been moved to the tmp#       directory.  We need to get the R seeding issues worked out#       before these functions can be replaced.  In addition, they #       need to be documented one distribution at a time (see the#       existing documentation for an example).#### Wishart### rwish delivers a pseudo-random Wishart deviate## USAGE:##   A <- rwish(v, S)## INPUT:##   v    degrees of freedom##   S    Scale matrix## OUTPUT:##  A     a pseudo-random Wishart deviate## Based on code originally posted by Bill Venables to S-news# on 6/11/1998## KQ on 2/5/2001"rwish" <-  function(v, S) {    if (!is.matrix(S))      S <- matrix(S)    if (nrow(S) != ncol(S)) {      stop(message="S not square in rwish().\n")    }    if (v < nrow(S)) {      stop(message="v is less than the dimension of S in rwish().\n")    }    p <- nrow(S)    CC <- chol(S)     Z <- matrix(0, p, p)    diag(Z) <- sqrt(rchisq(p, v:(v-p+1)))    if(p > 1) {      pseq <- 1:(p-1)      Z[rep(p*pseq, pseq) + unlist(lapply(pseq, seq))] <- rnorm(p*(p-1)/2)    }    return(crossprod(Z %*% CC))  }# dwish evaluations the Wishart pdf at positive definite matrix W.# note: uses the Gelman, et. al. parameterization.## USAGE:##   x <- dwish(W, v, S)## INPUT:##   W    positive definite matrix at which to evaluate PDF##   v    degrees of freedom##   S    Scale matrix## OUTPUT:##   x    the PDF evaluated (scalar)## ADM 8/16/2002"dwish" <-  function(W, v, S) {    if (!is.matrix(S))      S <- matrix(S)    if (nrow(S) != ncol(S)){      stop(message="W not square in dwish()\n\n")    }    if (!is.matrix(W))      S <- matrix(W)    if (nrow(W) != ncol(W)){      stop(message="W not square in dwish()\n\n")    }       if(nrow(S) != ncol(W)){      stop(message="W and X of different dimensionality in dwish()\n\n")    }    if (v < nrow(S)){      stop(message="v is less than the dimension of S in  dwish()\n\n")    }        k <- nrow(S)      # denominator    gammapart <- 1    for(i in 1:k) {      gammapart <- gammapart * gamma((v + 1 - i)/2)    }     denom <- gammapart *  2^(v * k / 2) * pi^(k*(k-1)/4)      # numerator    detS <- det(S)    detW <- det(W)    hold <- solve(S) %*% W    tracehold <- sum(hold[row(hold) == col(hold)])      num <- detS^(-v/2) * detW^((v - k - 1)/2) * exp(-1/2 * tracehold)    return(num / denom)  }#### Inverse Wishart### riwish generates a draw from the inverse Wishart distribution# (using the Wishart generator)  "riwish" <-  function(v, S) {    return(solve(rwish(v,solve(S))))  }# diwish evaluates the inverse Wishart pdf at positive definite# matrix W.  note: uses the Gelman, et. al. parameterization.## USAGE:##   x <- diwish(W, v, S)## INPUT:##   W    positive definite matrix at which to evaluate PDF##   v    degrees of freedom##   S    Scale matrix## OUTPUT:##   x    the PDF evaluated (scalar)## ADM 8/16/2002 "diwish" <-  function(W, v, S) {    if (!is.matrix(S))      S <- matrix(S)    if (nrow(S) != ncol(S)){      stop("W not square in diwish().\n")    }    if (!is.matrix(W))      S <- matrix(W)    if (nrow(W) != ncol(W)){      stop("W not square in diwish().\n")    }       if(nrow(S) != ncol(W)){      stop("W and X of different dimensionality in diwish().\n")    }    if (v < nrow(S)){      stop("v is less than the dimension of S in  diwish().\n")    }        k <- nrow(S)       # denominator    gammapart <- 1    for(i in 1:k) {      gammapart <- gammapart * gamma((v + 1 - i)/2)    }     denom <- gammapart *  2^(v * k / 2) * pi^(k*(k-1)/4)      # numerator    detS <- det(S)    detW <- det(W)    hold <- S %*% solve(W)    tracehold <- sum(hold[row(hold) == col(hold)])      num <- detS^(v/2) * detW^(-(v + k + 1)/2) * exp(-1/2 * tracehold)    return(num / denom)  }#### Inverse Gamma#### evaluate the inverse gamma density#### Kevin Rompala 5/6/2003## fixed KQ 3/8/2005"dinvgamma" <-  function(x, shape, scale = 1) {    # error checking    if(shape <= 0 | scale <=0) {      stop("Shape or scale parameter negative in dinvgamma().\n")    }        alpha <- shape    beta <- scale       # done on log scale to allow for large alphas and betas    log.density <- alpha * log(beta) - lgamma(alpha) -       (alpha + 1) * log(x) - (beta/x)    return(exp(log.density))  }## generate draws from the inverse gamma density (using## the gamma simulator)#### Kevin Rompala 5/6/2003## fixed KQ 3/8/2005"rinvgamma" <-  function(n, shape, scale = 1) {    return(1 / rgamma(n, shape, scale))  }#### Dirichlet (Multivariate Beta)### ddirichlet evaluates the density of the Dirichlet at# vector x given shape parameter vector (or matrix)# alpha.## note: this code is taken verbatim from the R-package# "Greg's Miscellaneous Functions" maintained by# Gregory R. Warnes <Gregory_R_Warnes@groton.pfizer.com>## Kevin Rompala 5/6/2003"ddirichlet" <-  function(x, alpha) {    dirichlet1 <- function(x, alpha) {      logD <- sum(lgamma(alpha)) - lgamma(sum(alpha))      s <- sum((alpha-1)*log(x))      exp(sum(s)-logD)    }    # make sure x is a matrix    if(!is.matrix(x))      if(is.data.frame(x))        x <- as.matrix(x)      else        x <- t(x)    if(!is.matrix(alpha))      alpha <- matrix( alpha, ncol=length(alpha), nrow=nrow(x), byrow=TRUE)    if( any(dim(x) != dim(alpha)) )      stop("Mismatch between dimensions of x and alpha in ddirichlet().\n")    pd <- vector(length=nrow(x))    for(i in 1:nrow(x))      pd[i] <- dirichlet1(x[i,],alpha[i,])    # Enforce 0 <= x[i,j] <= 1, sum(x[i,]) = 1    pd[ apply( x, 1, function(z) any( z <0 | z > 1)) ] <- 0    pd[ apply( x, 1, function(z) all.equal(sum( z ),1) !=TRUE) ] <- 0    return(pd)  }# rdirichlet generates n random draws from the Dirichlet at# vector x given shape parameter vector (or matrix)# alpha.## note: this code is taken verbatim from the R-package# "Greg's Miscellaneous Functions" maintained by# Gregory R. Warnes <Gregory_R_Warnes@groton.pfizer.com>## Kevin Rompala 5/6/2003"rdirichlet" <-  function(n, alpha) {    l <- length(alpha)    x <- matrix(rgamma(l*n,alpha),ncol=l,byrow=TRUE)    sm <- x%*%rep(1,l)    return(x/as.vector(sm))  }#### Non-Central Hypergeometric### code to evaluate the noncentral hypergeometric density (at a single point# or at all defined points).## parameters:##    n1, n2 -- number of subjects in group 1 and 2##    Y1, Y2 -- number of subjects with positive outcome [unobserved]##    psi -- odds ratio##    m1 -- sum of observed values of Y1 and Y2 (Y1 + Y2)#   # output:##   pi -- Pr(Y1 = x | Y1 + Y2 = m1) x=ll,...,uu##   for ll = max(0, m1-n2) and uu = min(n1, m1)#  # if x is NA, then a matrix is returned, with the first column the possible# values of x, and the second columns the probabilities.  if x is a scalar, # the density is evaluated at that point.## ADM on 5/8/2003## note: code adapted from R code published in conjunction with:## Liao, J.G. And Rosen, O. (2001) Fast and Stable Algorithms for Computing and # Sampling from the Noncentral Hypergeometric Distribution.  The American# Statistician 55, 366-369.#"dnoncenhypergeom" <-  function (x = NA, n1, n2, m1, psi) {    ##    ## AUXILIARY FUNCTIONS    ##    mode.compute <- function(n1, n2, m1, psi, ll, uu) {      a <- psi - 1      b <- -( (m1+n1+2)*psi + n2-m1 )           c <- psi*(n1+1)*(m1+1)      q <- b + sign(b)*sqrt(b*b-4*a*c)      q <- -q/2                               mode <- trunc(c/q)       if(uu>=mode && mode>=ll) return(mode)      else return( trunc(q/a) )          }    r.function <- function(n1, n2, m1, psi, i) {      (n1-i+1)*(m1-i+1)/i/(n2-m1+i)*psi    }    ##    ## MAIN FUNCTION    ##    # upper and lower limits for density evaluation    ll <- max(0, m1-n2)    uu <- min(n1, m1)    # check parameters    if(n1 < 0 | n2 < 0) {       stop("n1 or n2 negative in dnoncenhypergeom().\n")    }    if(m1 < 0 | m1 > (n1 + n2)) {       stop("m1 out of range in dnoncenhypergeom().\n")    }    if(psi <=0) {       stop("psi [odds ratio] negative in dnoncenhypergeom().\n")    }    if(!is.na(x) & (x < ll | x > uu)) {       stop("x out of bounds in dnoncenhypergeom().\n")    }    if(!is.na(x) & length(x) > 1) {       stop("x neither missing or scalar in dnoncenhypergeom().\n")    }        # evaluate density using recursion (from mode)    mode <- mode.compute(n1, n2, m1, psi, ll, uu)    pi <- array(1, uu-ll+1)    shift <- 1-ll        if(mode<uu) { # note the shift of location      r1 <- r.function( n1, n2, m1, psi, (mode+1):uu )             pi[(mode+1 + shift):(uu + shift)] <- cumprod(r1)           }       if(mode>ll) {       r1 <- 1/r.function( n1, n2, m1, psi, mode:(ll+1) )       pi[(mode-1 + shift):(ll + shift)] <- cumprod(r1)    }                pi <- pi/sum(pi)    if(is.na(x)) return(cbind(ll:uu,pi))    else return(pi[x + shift])}# code to generate random deviates from the noncentral hypergeometric density ## parameters:##    n -- the number of draws to make##    n1, n2 -- number of subjects in group 1 and 2##    Y1, Y2 -- number of subjects with positive outcome [unobserved]##    psi -- odds ratio##    m1 -- sum of observed values of Y1 and Y2 (Y1 + Y2)#   # output:##   output -- a list of length n of random deviates#  ## ADM on 5/9/2003## note: code adapted from R code published in conjunction with:## Liao, J.G. And Rosen, O. (2001) Fast and Stable Algorithms for Computing and # Sampling from the Noncentral Hypergeometric Distribution.  The American# Statistician 55, 366-369.#"rnoncenhypergeom" <-  function (n, n1, n2, m1, psi) {    ##    ## AUXILIARY FUNCTIONS    ##      mode.compute <- function(n1, n2, m1, psi, ll, uu) {      a <- psi - 1      b <- -( (m1+n1+2)*psi + n2-m1 )           c <- psi*(n1+1)*(m1+1)      q <- b + sign(b)*sqrt(b*b-4*a*c)      q <- -q/2                               mode <- trunc(c/q)       if(uu>=mode && mode>=ll) return(mode)      else return( trunc(q/a) )          }        sample.low.to.high <- function(lower.end, ran, pi, shift) {       for(i in lower.end:uu) {                                        if(ran <= pi[i+shift]) return(i)        ran <- ran - pi[i+shift]        }                                    }           sample.high.to.low <- function(upper.end, ran, pi, shift) {      for(i in upper.end:ll) {                                      if(ran <= pi[i+shift]) return(i)        ran <- ran - pi[i+shift]      }     }        single.draw <- function(n1, n2, m1, psi, ll, uu, mode, pi) {      ran <- runif(1)      shift <- 1-ll        if(mode==ll) return(sample.low.to.high(ll, ran, pi, shift))                  if(mode==uu) return(sample.high.to.low(uu, ran, pi, shift))                                               if(ran < pi[mode+shift]) return(mode)                   ran <- ran - pi[mode+shift]      lower <- mode - 1                                                                                  upper <- mode + 1                repeat {                   if(pi[upper + shift] >= pi[lower + shift]) {                        if(ran < pi[upper+shift]) return(upper)          ran <- ran - pi[upper+shift]          if(upper == uu) return( sample.high.to.low(lower, ran, pi, shift) )          upper <- upper + 1                                    }        else {          if(ran < pi[lower+shift]) return(lower)          ran <- ran - pi[lower+shift]          if(lower == ll) return( sample.low.to.high(upper, ran, pi, shift) )          lower <- lower - 1                           }           }    }      ##    ## MAIN FUNCTION    ##    # upper and lower limits for density evaluation    ll <- max(0, m1-n2)    uu <- min(n1, m1)        # check parameters    if(n1 < 0 | n2 < 0) {       stop("n1 or n2 negative in rnoncenhypergeom().\n")    }    if(m1 < 0 | m1 > (n1 + n2)) {       stop("m1 out of range in rnoncenhypergeom().\n")    }    if(psi <=0) {       stop("psi [odds ratio] negative in rnoncenhypergeom().\n")    }    # get density and other parameters    mode <- mode.compute(n1, n2, m1, psi, ll, uu)     pi <- dnoncenhypergeom(NA, n1, n2, m1, psi)[,2]        output <- array(0,n)    for(i in 1:n) output[i] <- single.draw(n1, n2, m1, psi, ll, uu, mode, pi)        return(output)  }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -