Nothing
## Will Townes' deviance-based feature ranking
## Downloaded from:
## https://github.com/willtownes/scrna2019/blob/master/util/functions.R
## GNU Lesser General Public License v3.0
##### Deviance functions #####
poisson_deviance<-function(x,mu,sz){
#assumes log link and size factor sz on the same scale as x (not logged)
#stopifnot(all(x>=0 & sz>0))
2*sum(x*log(x/(sz*mu)),na.rm=TRUE)-2*sum(x-sz*mu)
}
multinomial_deviance<-function(x,p){
-2*sum(x*log(p))
}
binomial_deviance<-function(x,p,n){
term1<-sum(x*log(x/(n*p)), na.rm=TRUE)
nx<-n-x
term2<-sum(nx*log(nx/(n*(1-p))), na.rm=TRUE)
2*(term1+term2)
}
gof_func<-function(x,sz,mod=c("binomial","multinomial","poisson","geometric")){
#Let n=colSums(original matrix where x is a row)
#if binomial, assumes sz=n, required! So sz>0 for whole vector
#if poisson, assumes sz=n/geometric_mean(n), so again all of sz>0
#if geometric, assumes sz=log(n/geometric_mean(n)) which helps numerical stability. Here sz can be <>0
#note sum(x)/sum(sz) is the (scalar) MLE for "mu" in Poisson and "p" in Binomial
mod<-match.arg(mod)
fit<-list(deviance=0,df.residual=length(x)-1,converged=TRUE)
if(mod=="multinomial"){
fit$deviance<-multinomial_deviance(x,sum(x)/sum(sz))
} else if(mod=="binomial"){
fit$deviance<-binomial_deviance(x,sum(x)/sum(sz),sz)
} else if(mod=="poisson"){
fit$deviance<-poisson_deviance(x,sum(x)/sum(sz),sz)
} else if(mod=="geometric"){
if(any(x>0)) {
fit<-glm(x~offset(sz),family=MASS::negative.binomial(theta=1))
}
} else { stop("invalid model") }
if(fit$converged){
dev<-fit$deviance
df<-fit$df.residual #length(x)-1
pval<-pchisq(dev,df,lower.tail=FALSE)
res<-c(dev,pval)
} else {
res<-rep(NA,2)
}
names(res)<-c("deviance","pval")
res
}
compute_size_factors<-function(m,mod=c("binomial","multinomial","poisson","geometric")){
#given matrix m with samples in the columns
#compute size factors suitable for the discrete model in 'mod'
mod<-match.arg(mod)
sz<-Matrix::colSums(m) #base case, multinomial or binomial
if(mod %in% c("multinomial","binomial")){ return(sz) }
sz<-log(sz)
sz<-sz - mean(sz) #make geometric mean of sz be 1 for poisson, geometric
if(mod=="poisson"){ return(exp(sz)) }
sz #geometric, use log scale size factors
}
compute_gene_info<-function(m,gmeta=NULL,mod=c("binomial","multinomial","poisson","geometric")){
#m a data matrix with genes=rows
#gmeta a pre-existing data frame with gene-level metadata
mod<-match.arg(mod)
if(!is.null(gmeta)){ stopifnot(nrow(m)==nrow(gmeta)) }
gnz<-Matrix::rowSums(m>0)
sz<-compute_size_factors(m,mod)
gof<-function(g){ gof_func(m[g,],sz,mod) }
gof<-as.data.frame(t(vapply(1:nrow(m),gof,FUN.VALUE=rep(0.0,2))))
#colnames(gof)<-c("deviance","pval")
gmu<-Matrix::rowMeans(m)
gvar<-apply(m,1,var)
gfano<-ifelse(gvar>0 & gmu>0, gvar/gmu, 0)
res<-cbind(nzsum=gnz,fano=gfano,gof)
res$pval_fdr<-p.adjust(res$pval,"BH")
if(is.null(gmeta)){ return(res) } else { return(cbind(gmeta,res)) }
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.