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

📄 mcmcmixfactanal.r

📁 使用R语言的马尔科夫链蒙特卡洛模拟(MCMC)源代码程序。
💻 R
字号:
############################################################################ sample from the posterior distribution of a factor analysis model## model in R using linked C++ code in Scythe.#### The model is:#### x*_i = \Lambda \phi_i + \epsilon_i,   \epsilon_i \sim N(0, \Psi)#### \lambda_{ij} \sim N(l0_{ij}, L0^{-1}_{ij})## \phi_i \sim N(0,I)#### and x*_i is the latent variable formed from the observed ordinal## variable in the usual (Albert and Chib, 1993) way and is equal to## x_i when x_i is continuous. When x_j is ordinal \Psi_jj is assumed## to be 1.#### Andrew D. Martin## Washington University#### Kevin M. Quinn## Harvard University#### 12/2/2003## Revised to accommodate new spec 7/20/2004## Minor bug fix regarding std.mean 6/25/2004############################################################################"MCMCmixfactanal" <-  function(x, factors, lambda.constraints=list(),           data=parent.frame(), burnin = 1000, mcmc = 20000,           thin=1, tune=NA, verbose = 0, seed = NA,           lambda.start = NA, psi.start=NA,           l0=0, L0=0, a0=0.001, b0=0.001,           store.lambda=TRUE, store.scores=FALSE,           std.mean=TRUE, std.var=TRUE, ... ) {        call <- match.call()    echo.name <- NULL    mt <- terms(x, data=data)    if (attr(mt, "response") > 0)       stop("Response not allowed in formula in MCMCmixfactanal().\n")    if(missing(data)) data <- sys.frame(sys.parent())    mf <- match.call(expand.dots = FALSE)    mf$factors <- mf$lambda.constraints <- mf$burnin <- mf$mcmc <- NULL    mf$thin <- mf$tune <- mf$verbose <- mf$seed <- NULL    mf$lambda.start <- mf$l0 <- mf$L0 <- mf$a0 <- mf$b0 <- NULL    mf$store.lambda <- mf$store.scores <- mf$std.mean <- NULL    mf$std.var <- mf$... <- NULL    mf$drop.unused.levels <- TRUE    mf[[1]] <- as.name("model.frame")    mf$na.action <- 'na.pass'    mf <- eval(mf, sys.frame(sys.parent()))    attributes(mt)$intercept <- 0    Xterm.length <- length(attr(mt, "variables"))    X <- subset(mf,                select=as.character(attr(mt, "variables"))[2:Xterm.length])    N <- nrow(X)	      # number of observations          K <- ncol(X)              # number of manifest variables    ncat <- matrix(NA, K, 1)  # vector of number of categ. in each man. var.     for (i in 1:K){       if (is.numeric(X[,i])){        ncat[i] <- -999        X[is.na(X[,i]), i] <- -999      }   else if (is.ordered(X[, i])) {     ncat[i] <- nlevels(X[, i])     temp <- as.integer(X[,i])     temp <- ifelse(is.na(X[,i]) | (X[,i] == "<NA>"), -999, temp)     X[, i] <- temp   }   else {        stop("Manifest variable ", dimnames(X)[[2]][i],             " neither ordered factor nor numeric variable.\n")      }    }        X <- as.matrix(X)    xvars <- dimnames(X)[[2]] # X variable names    xobs <- dimnames(X)[[1]]  # observation names        if (is.null(xobs)){      xobs <- 1:N    }    # standardize X    if (std.mean){      for (i in 1:K){        if (ncat[i] == -999){          X[,i] <- X[,i]-mean(X[,i])        }      }    }    if (std.var){      for (i in 1:K){        if (ncat[i] == -999){          X[,i] <- (X[,i] - mean(X[,i]))/sd(X[,i]) + mean(X[,i])        }      }    }        n.ord.ge3 <- 0    for (i in 1:K)      if (ncat[i] >= 3) n.ord.ge3 <- n.ord.ge3 + 1       check.mcmc.parameters(burnin, mcmc, thin)        ## setup constraints on Lambda    holder <- build.factor.constraints(lambda.constraints, X, K, factors+1)    Lambda.eq.constraints <- holder[[1]]    Lambda.ineq.constraints <- holder[[2]]    X.names <- holder[[3]]        ## if subtracting out the mean of continuous X then constrain    ## the mean parameter to 0    for (i in 1:K){      if (ncat[i] < 2 && std.mean==TRUE){        if ((Lambda.eq.constraints[i,1] == -999 ||             Lambda.eq.constraints[i,1] == 0.0) &&            Lambda.ineq.constraints[i,1] == 0.0){          Lambda.eq.constraints[i,1] <- 0.0        }        else {          cat("Constraints on Lambda are logically\ninconsistent with std.mean==TRUE.\n")          stop("Please respecify and call MCMCmixfactanal() again\n")                  }      }    }        ## setup and check prior on Psi    holder <- form.ig.diagmat.prior(a0, b0, K)    a0 <- holder[[1]]    b0 <- holder[[2]]    ## setup prior on Lambda    holder <- form.factload.norm.prior(l0, L0, K, factors+1, X.names)    Lambda.prior.mean <- holder[[1]]    Lambda.prior.prec <- holder[[2]]    # seeds    seeds <- form.seeds(seed)     lecuyer <- seeds[[1]]    seed.array <- seeds[[2]]    lecuyer.stream <- seeds[[3]]        # Starting values for Lambda    Lambda <- matrix(0, K, factors+1)    if (is.na(lambda.start)){# sets Lambda to equality constraints & 0s      for (i in 1:K){        for (j in 1:(factors+1)){          if (Lambda.eq.constraints[i,j]==-999){            if(Lambda.ineq.constraints[i,j]==0){              if (j==1){                if (ncat[i] < 2){                  Lambda[i,j] <- mean(X[,i]!=-999)                }                if (ncat[i] == 2){                  probit.out <- glm(as.factor(X[X[,i]!=-999,i])~1,                                    family=binomial(link=probit))                  probit.beta <- coef(probit.out)                  Lambda[i,j] <- probit.beta[1]                }                if (ncat[i] > 2){                  polr.out <- polr(ordered(X[X[,i]!=-999,i])~1)                  Lambda[i,j] <- -polr.out$zeta[1]*.588                }              }            }            if(Lambda.ineq.constraints[i,j]>0){              Lambda[i,j] <- 1.0            }            if(Lambda.ineq.constraints[i,j]<0){              Lambda[i,j] <- -1.0            }                    }          else Lambda[i,j] <- Lambda.eq.constraints[i,j]        }      }        }    else if (is.matrix(lambda.start)){      if (nrow(lambda.start)==K && ncol(lambda.start)==(factors+1))        Lambda  <- lambda.start      else {        cat("Starting values not of correct size for model specification.\n")        stop("Please respecify and call ", echo.name, "() again\n")      }    }    else if (length(lambda.start)==1 && is.numeric(lambda.start)){      Lambda <- matrix(lambda.start, K, factors+1)      for (i in 1:K){        for (j in 1:(factors+1)){          if (Lambda.eq.constraints[i,j] != -999)            Lambda[i,j] <- Lambda.eq.constraints[i,j]        }      }        }    else {      cat("Starting values neither NA, matrix, nor scalar.\n")      stop("Please respecify and call ", echo.name, "() again\n")    }        # check MH tuning parameter    if (is.na(tune)){      tune <- matrix(NA, K, 1)      for (i in 1:K){        tune[i] <- abs(0.05/ncat[i])      }    }    else if (is.double(tune)){      tune <- matrix(abs(tune/ncat), K, 1)    }      # starting values for gamma (note: not changeable by user)    if (max(ncat) <= 2){      gamma <- matrix(0, 3, K)    }    else {      gamma <- matrix(0, max(ncat)+1, K)    }    for (i in 1:K){      if (ncat[i]<=2){        gamma[1,i] <- -300        gamma[2,i] <- 0        gamma[3,i] <- 300      }      if(ncat[i] > 2) {        polr.out <- polr(ordered(X[X[,i]!=-999,i])~1)        gamma[1,i] <- -300        gamma[2,i] <- 0        gamma[3:ncat[i],i] <- (polr.out$zeta[2:(ncat[i]-1)] -                               polr.out$zeta[1])*.588        gamma[ncat[i]+1,i] <- 300      }    }    ## starting values for Psi    Psi <- factuniqueness.start(psi.start, X)    for (i in 1:K){      if (ncat[i] >= 2){        Psi[i,i] <- 1.0      }    }              # define holder for posterior sample    if (store.scores == FALSE && store.lambda == FALSE){      sample <- matrix(data=0, mcmc/thin, length(gamma)+K)    }    else if (store.scores == TRUE && store.lambda == FALSE){      sample <- matrix(data=0, mcmc/thin, (factors+1)*N + length(gamma)+K)    }    else if(store.scores == FALSE && store.lambda == TRUE) {      sample <- matrix(data=0, mcmc/thin, K*(factors+1)+length(gamma)+K)    }    else { # store.scores==TRUE && store.lambda==TRUE      sample <- matrix(data=0, mcmc/thin, K*(factors+1)+(factors+1)*N +                       length(gamma)+K)    }    accepts <- matrix(0, K, 1)    # Call the C++ code to do the real work    posterior <- NULL    posterior <- .C("mixfactanalpost",                    samdata = as.double(sample),                    samrow = as.integer(nrow(sample)),                    samcol = as.integer(ncol(sample)),                    X = as.double(X),                    Xrow = as.integer(nrow(X)),                    Xcol = as.integer(ncol(X)),                    burnin = as.integer(burnin),                    mcmc = as.integer(mcmc),                    thin = as.integer(thin),                    tune = as.double(tune),                    lecuyer = as.integer(lecuyer),                    seedarray = as.integer(seed.array),                    lecuyerstream = as.integer(lecuyer.stream),                    verbose = as.integer(verbose),                    Lambda = as.double(Lambda),                    Lambdarow = as.integer(nrow(Lambda)),                    Lambdacol = as.integer(ncol(Lambda)),                    gamma = as.double(gamma),                    gammarow = as.integer(nrow(gamma)),                    gammacol = as.integer(ncol(gamma)),                    Psi = as.double(Psi),                    Psirow = as.integer(nrow(Psi)),                    Psicol = as.integer(ncol(Psi)),                    ncat = as.integer(ncat),                    ncatrow = as.integer(nrow(ncat)),                    ncatcol = as.integer(ncol(ncat)),                    Lameq = as.double(Lambda.eq.constraints),                    Lameqrow = as.integer(nrow(Lambda.eq.constraints)),                    Lameqcol = as.integer(ncol(Lambda.ineq.constraints)),                    Lamineq = as.double(Lambda.ineq.constraints),                    Lamineqrow = as.integer(nrow(Lambda.ineq.constraints)),                    Lamineqcol = as.integer(ncol(Lambda.ineq.constraints)),                    Lampmean = as.double(Lambda.prior.mean),                    Lampmeanrow = as.integer(nrow(Lambda.prior.mean)),                    Lampmeancol = as.integer(ncol(Lambda.prior.prec)),                    Lampprec = as.double(Lambda.prior.prec),                    Lampprecrow = as.integer(nrow(Lambda.prior.prec)),                    Lamppreccol = as.integer(ncol(Lambda.prior.prec)),                    a0 = as.double(a0),                    a0row = as.integer(nrow(a0)),                    a0col = as.integer(ncol(a0)),                    b0 = as.double(b0),                    b0row = as.integer(nrow(b0)),                    b0col = as.integer(ncol(b0)),                    storelambda = as.integer(store.lambda),                    storescores = as.integer(store.scores),                    accepts = as.integer(accepts),                    acceptsrow = as.integer(nrow(accepts)),                    acceptscol = as.integer(ncol(accepts)),                    PACKAGE="MCMCpack"                    )    accepts <- matrix(posterior$accepts, posterior$acceptsrow,                      posterior$acceptscol, byrow=TRUE)    rownames(accepts) <- X.names    colnames(accepts) <- ""    cat("\n\nAcceptance rates:\n")    print(t(accepts) / (posterior$burnin+posterior$mcmc), digits=2,          width=6)                  # put together matrix and build MCMC object to return    sample <- matrix(posterior$samdata, posterior$samrow, posterior$samcol,                     byrow=FALSE)    output <- mcmc(data=sample,start=1, end=mcmc, thin=thin)        par.names <- NULL    if (store.lambda==TRUE){      Lambda.names <- paste(paste("Lambda",                                  rep(X.names,                                      each=(factors+1)), sep=""),                            rep(1:(factors+1),K), sep=".")      par.names <- c(par.names, Lambda.names)    }        gamma.names <- paste(paste("gamma",                               rep(0:(nrow(gamma)-1),                                   each=K), sep=""),                         rep(X.names,  nrow(gamma)), sep=".")    par.names <- c(par.names, gamma.names)        if (store.scores==TRUE){      phi.names <- paste(paste("phi",                               rep(xobs, each=(factors+1)), sep="."),                         rep(1:(factors+1),(factors+1)), sep=".")      par.names <- c(par.names, phi.names)    }    Psi.names <- paste("Psi", X.names, sep=".")    par.names <- c(par.names, Psi.names)        varnames(output) <- par.names    # get rid of columns for constrained parameters    output.df <- as.data.frame(as.matrix(output))    output.var <- diag(var(output.df))    output.df <- output.df[,output.var != 0]    output <- mcmc(as.matrix(output.df), start=burnin+1, end=burnin+mcmc,                   thin=thin)        # add constraint info so this isn't lost    attr(output, "constraints") <- lambda.constraints    attr(output, "n.manifest") <- K    attr(output, "n.factors") <- factors    attr(output, "accept.rates") <- t(accepts) / (posterior$burnin+posterior$mcmc)      attr(output,"title") <-        "MCMCpack Mixed Data Factor Analysis Posterior Sample"        return(output)      }

⌨️ 快捷键说明

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