#' @eval get_description('HSDEM')
#' @include mixed_effect_class.R HSD_class.R
#' @export HSDEM
#' @examples
#' D = iris_DatasetExperiment()
#' D$sample_meta$id=rownames(D) # dummy id column
#' M = HSDEM(formula = y~Species+ Error(id/Species))
#' M = model_apply(M,D)
#'
HSDEM = function(alpha=0.05,mtc='fdr',formula,...) {
out=struct::new_struct('HSDEM',
alpha=alpha,
mtc=mtc,
formula=formula,
...)
return(out)
}
.HSDEM<-setClass(
"HSDEM",
contains=c('model'),
slots=c(
# INPUTS
alpha='entity',
mtc='enum',
formula='entity',
# OUTPUTS
p_value='entity',
significant='entity'
),
prototype = list(name="Tukey's Honest Significant Difference using estimated marginal means",
description=paste0("Tukey's HSD post hoc test is a modified t-test ",
'applied for all features to all pairs of levels in a factor. ',
'It is used to determine which groups are different (if any). A multiple ',
'test corrected p-value is computed to indicate which groups are ',
'significantly different to the others for each feature. ',
'For mixed effects models estimated marginal means are used.'),
type="univariate",
predicted='p_value',
ontology="STATO:0000187",
libraries=c('emmeans','nlme'),
.params=c('alpha','mtc','formula'),
.outputs=c('p_value','significant'),
alpha=ents$alpha,
mtc=ents$mtc,
formula=ents$formula,
p_value=ents$p_value,
significant=ents$significant
)
)
#' @export
#' @template model_apply
setMethod(f="model_apply",
signature=c("HSDEM",'DatasetExperiment'),
definition=function(M,D) {
X=D$data
lmer_formula=aov2lme(M$formula)
var_names=all.vars(M$formula)
var_names_1=var_names[1]
var_names=var_names[-1]
y=D$sample_meta[var_names]
# set the contrasts
O=options('contrasts') # keep the old ones
options(contrasts = c("contr.sum","contr.poly"))
# attempt to detect within factors
within=which(var_names %in% all.names(M$formula)[which('Error'== all.names(M$formula))+2])
if (length(within)>0) {
var_names_ex=var_names[-within]
} else {
var_names_ex=var_names
}
FF=full_fact(var_names_ex)
FF=apply(FF,1,function(x) var_names_ex[x==1])
FF=FF[-1]
output=apply(X,2,function(x) {
temp=y
temp[[var_names_1]]=scale(x,center = TRUE,scale=TRUE)
dona=FALSE
testlm=tryCatch({ # if any warnings/messages set p-values to NA as unreliable
LM=nlme::lme(lmer_formula$f,random=lmer_formula$random,method='ML',data=temp,na.action=na.omit)
}, warning = function(w) {
NA
}, message = function(m) {
NA
}, error = function(e) {
NA
})
output2=list()
for (k in 1:length(FF)) {
if (!is.na(testlm[[1]])) {
testhsd=tryCatch({
output2[[k]]=as.data.frame(
pairs(
emmeans::emmeans(LM,FF[[k]],
data=temp)))
}, warning = function(w) {
NA
} , message = function(m) {
NA
}, error = function(e) {
NA
})
if (!is.data.frame(testhsd[1])) {
output2[[k]]=NA
}
} else {
output2[[k]]=NA
}
}
return(output2)
})
p_value=lapply(output,function(x) {
x=as.data.frame(x)
return(x$p.value)
})
ln=length(p_value[[1]])
p_value=lapply(p_value,function(x){
if (length(x)!=ln) {
return(p_value[[1]]*NA)
} else {
return(x)
}
})
p_value=do.call("rbind",p_value)
p_value=data.frame(p_value)
colnames(p_value)=as.data.frame(output[[1]])$contrast
# fdr correct
M$p_value=as.data.frame(apply(p_value,2,p.adjust,method=M$mtc))
M$significant=as.data.frame(M$p_value<M$alpha)
# reset contrasts
options(O)
return(M)
}
)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.