# This document contains two functions, stand.path.score and Bayes.model. The first one computes # the standardized pathway score for any given pathway, and the second function performs Bayesian # logistic regression for 1 or more than 1 pathways. # Two examples are provided in this document. Input data and example output are attached. The gene expression # data for illustration were a subset of the data with accession number GSE69240 from NCBI GEO database. # Note: For the Bayesian analysis, "OpenBUGS" and the R packages "R2OpenBIGS" need to be installed install.packages("R2OpenBUGS") library(R2OpenBUGS) ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### For each pathway, this function computes the standardized pathway scores for all samples. ### Function "stand.path.score" computes the standardized pathway scores in each pathway. ### This function is called in "Bayes.model" for each pathway to compute pathway score. # stand.path.score <- function(exp.data, path.data, refgene.ID, exp.ID, path.ID){ # exp.data: matrix of complete gene expression data, number of rows is the number of genes, # number of columns is the number of subjects+2, the 1st column contains gene entry IDs # and 2nd column contains gene symbols # path.data: 2-column matrix, containing gene information in the pathway of interest (1st # column contains gene entry IDs and 2nd gene symbols respectively) # refgene.ID: character, the entry ID of the reference gene in this pathway # exp.ID: character, the variable name of the first column of exp.data # path.ID: character, the variable name of the first column of path.data # ------ combine expression data and pathway data ------ mydata <- merge(exp.data, path.data, by.x=exp.ID, by.y=path.ID, all=F)[, -(dim(exp.data)[2]+1)] # ------ 4 steps to compute standardized pathway scores ------ # 1. gene-gene correlation mymatrix <- as.matrix(mydata[1:dim(mydata)[1], 3:dim(mydata)[2]]) ref.gene <- c(which(mydata[,1]==refgene.ID)[1]) gene.corr <- c() for(i in 1:dim(mydata)[1]){ genecorr <- cor(mymatrix[ref.gene,], mymatrix[i,]) gene.corr[i] <- sign(genecorr) } # 2. rank gene expression rank.matrix <- matrix(,dim(mydata)[1], (dim(mydata)[2]-2)) for(j in 1:dim(mydata)[1]){ rank.matrix[j,] <- rank(abs(mydata[j, 3:dim(mydata)[2]])) } # 3. pathway score path.score <- colSums(gene.corr*rank.matrix)/dim(mydata)[1] # 4. standardized pathway score standardized.pathway.score <- (path.score - mean(path.score))/sd(path.score) standardized.pathway.score } ### End of computing standardized pathway scores. Repeat this function for multiple pathways. ############################################################################################# ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### Function for conducting the Bayesian logistic regression with r2openbugs. # Bayes.model <- function(exp.data, status, pathway.name, pathway.data, no.path, ref.gene.ID, exp.ID, path.ID, model.file, no.iter=6000, no.chains=1, no.burnin=1000, no.thin=10){ # exp.data: matrix of complete gene expression data, # number of rows is the number of genes, number of columns is the number of subjects+2, # the 1st column contains gene entry IDs and 2nd column contains gene symbols # status: vector of disease status, length is the number of subjects # pathway.name: vector of pathway names # pathway.data: list of information of the competing pathways, each sublist corresponds to a # single pathway and contains 2 columns (1st for gene IDs and 2nd for gene symbols) # no.path: number of competing pathways # ref.gene.ID: a vector of reference gene IDs for each competing pathway # exp.ID: character, the variable name of the first column of exp.data # path.ID: character, the variable name of the first column of path.data # model.file: user-defined filename containing the path to save the Bayesian model, required # in OpenBUGS # no.iter: number of iterations for Bayesian model (Default is 6000) # no.chains: number of Markov chains in the MCMC procedure (Default is 1) # no.burnin: length of burn in (Default is 1000) # no.thin: thinning rate (Default is 10) # A total of 5000 posterior samples will be included based on default settings basename(model.file) # save the full Bayesian model in "model.file" # ------ model specification ------ model <- function(){ # Specify prior distributions for regression coefficients beta0 ~ dnorm(0, 1.0E-2); # prior for intercept for(j in 1:(nob-1)){ # prior for pathway effects, nob-1= number of pathways beta1[j] ~ dnorm(0, 1.0E-2); } for(i in 1:I){ # likelihood pathdata[i, 1] ~ dbin(p[i], 1); logit(p[i])<- beta0 + inprod(beta1[], pathdata[i,2:nob]); } } # ----- End of model specification ----- write.model(model, model.file) # ------ data input ----- data0 <- status for(t in 1:no.path){ data1 <- stand.path.score(exp.data, path.data=pathway.data[[t]], refgene.ID=ref.gene.ID[t], exp.ID, path.ID) data0 <- cbind(data0, data1) } colnames(data0) <- c("status", pathway.name) pathdata <- as.matrix(data0) I <- dim(pathdata)[1] nob <- dim(pathdata)[2] # number of competing pathways+1 data <- list("I", "nob", "pathdata") # complete data input inits <- function() { list(beta0=0, beta1=c(rep(0,(nob-1)))) } params <- c("beta0", "beta1") # ----- BUGS analysis ----- out <- bugs(data, inits, params, model.file, n.iter=no.iter, n.chains=no.chains, n.burnin=no.burnin, n.thin=no.thin) pD <- out$pD DIC <- out$DIC # ----- compute posterior probability ----- betapositive <- c() betanegative <- c() mysize <- length(out$sims.matrix[,1]) for(u in 2:(length(out$sims.matrix[2,])-1)){ betapositive[u] <- length(which(out$sims.matrix[,u]>0))/mysize betanegative[u] <- length(which(out$sims.matrix[,u]<0))/mysize } posterior.prob <- c() for(v in 2:(length(out$sims.matrix[2,])-1)){ posterior.prob[v-1] <- max(betapositive[v], betanegative[v]) } # ----- table for ranks ----- myrank <- rank(-posterior.prob) out.put <- as.data.frame(cbind(pathway.name, myrank, posterior.prob)) colnames(out.put) <- c("Pathway", "Rank", "Posterior probability") # ----- prepare output, explained below ----- infor <- as.data.frame(matrix(c(pD, DIC, I), 1, 3)) colnames(infor) <- c("pD", "DIC", "Sample size") list(rank.table=out.put[order(myrank),], summary=out$summary, infor=infor, posterior.sample=out$sims.matrix, history=out$sims.array[, 1, ], stand.pathway.score=data0) } # End of function # Variables in the above output are: # rank.table: includes the ranks of pathways and corresponding posterior probabilities. # summary: summary statistics of posterior samples of effect size including mean, sd, # 2.5% quantile, 25% quantile, 50% quantile, 75% quantile and 97.5% quantile. # infor: infor includes pD, DIC, and Sample size. # posterior.sample: all posterior.samples of effect size. # history: history of all posterior samples # stand.pathway.score: now includes disease status and standardized pathway score. ### End of function for conducting the Bayesian logistic regression with r2openbugs. ############################################################################################## # --------- Example --------- --------- Example --------- --------- Example --------- # # Details are in the R markdown document. # The file "exp_data" contains information about genes and gene expression data. ############################################################################################## # Example 1: Bayesian analysis with two competing pathways A and B # "path_A" is a pathway including 20 genes. # "path_B" is a pathway including 16 genes. path_data_AB <- list(path_A, path_B) result_AB <- Bayes.model(exp.data=exp_data, status=c(rep(0,5),rep(1,5)), pathway.name=c("path_A","path_B"), pathway.data=path_data_AB, no.path=2, ref.gene.ID=c(396, 62), exp.ID="EntrezGeneID", path.ID="geneid", model.file="C:/mymodel_1.odc", no.iter=6000, no.chains=1, no.burnin=1000, no.thin=10) ############################################################################################## # Example 2: Bayesian analysis with two competing pathways C and D # "path_C1" is a pathway including 10 genes and two subpathways called "path_C2" and "path_C3". # "path_C2" is a subpathway of "path_C1" and it includes 10 genes. # "path_C3" is a subpathway of "path_C1" and it includes 10 genes. # "path_D1" is a pathway and it includes 6 genes and a subpathway called "path_D2". # "path_D2" is a subpathway of "path_D1" and it includes 10 genes. path_data_CD <- list(rbind(path_C1, path_C2, path_C3), rbind(path_D1, path_D2)) result_CD <- Bayes.model(exp.data=exp_data, status=c(rep(0,5),rep(1,5)), pathway.name=c("path_C", "path_D"), pathway.data=path_data_CD, no.path=2, ref.gene.ID=c(397, 61), exp.ID="EntrezGeneID", path.ID="geneid", model.file="C:/mymodel_2.odc", no.iter=6000, no.chains=1, no.burnin=1000, no.thin=10) ##############################################################################################