|
|
@ -0,0 +1,151 @@ |
|
|
|
impose.mono <- function(x, dir){ |
|
|
|
# Function to impose monotonicity on elements of the vector, x |
|
|
|
# dir="incr" gives increasing monotonicity |
|
|
|
# dir="decr" gives decreasing monotonicity |
|
|
|
|
|
|
|
if(dir=="decr"){ x <- rev(x) } |
|
|
|
for(i in 2:length(x)){ |
|
|
|
idx <- is.na(x[(i-1):i]) |
|
|
|
if (sum(idx)==1){ |
|
|
|
x[i] <- x[(i-1):i][!idx] |
|
|
|
} else { |
|
|
|
x[i] <- max(x[i-1],x[i]) |
|
|
|
} |
|
|
|
} |
|
|
|
if(dir=="decr"){ x <- rev(x) } |
|
|
|
x |
|
|
|
} |
|
|
|
|
|
|
|
### |
|
|
|
|
|
|
|
perm <- function(dat, nExp, nCtl){ |
|
|
|
N <- nExp+nCtl # total number of exp and neg ctl wells |
|
|
|
k <- NROW(dat) # number of peptide pools |
|
|
|
B <- choose(N,nExp) # number of perms needed for complete enumeration |
|
|
|
|
|
|
|
if(B < 20) stop("Too few replicates to use this method (B < 20).") |
|
|
|
|
|
|
|
mu.e <- rowMeans(dat[,1:nExp], na.rm=TRUE) # vector of peptide pool means |
|
|
|
mu.c <- rowMeans(dat[,nExp+(1:nCtl)], na.rm=TRUE) # vector of neg ctl means |
|
|
|
|
|
|
|
# test statistic for observed data |
|
|
|
t <- mu.e-mu.c |
|
|
|
t.sort <- sort(t) |
|
|
|
index <- order(t) |
|
|
|
|
|
|
|
# samp matrix contains all possible permutations of columns of dat matrix: |
|
|
|
samp <- expand.grid(rep(list(0:1),N)) |
|
|
|
samp <- samp[apply(samp,1,sum)==nExp,] |
|
|
|
samp <- as.matrix(samp) |
|
|
|
|
|
|
|
tPerm <- matrix(0,nrow=k,ncol=B) |
|
|
|
|
|
|
|
# calculate test statistics for each perm sample in samp: |
|
|
|
for(i in 1:B){ |
|
|
|
perm.dat <- dat[,order(samp[i,])] |
|
|
|
mu.exp <- rowMeans(perm.dat[,(1:nExp)+nCtl], na.rm=TRUE) |
|
|
|
mu.ctl <- rowMeans(perm.dat[,1:nCtl], na.rm=TRUE) |
|
|
|
tPerm[,i] <- mu.exp-mu.ctl |
|
|
|
} |
|
|
|
|
|
|
|
# order rows of tPerm to correspond with sorted test statistics in t.sort: |
|
|
|
if(k==1){ tPerm.mono <- tPerm.sort <- tPerm } |
|
|
|
if(k>1){ |
|
|
|
tPerm.sort <- tPerm[index,] |
|
|
|
tPerm.mono <- apply(tPerm.sort,2,impose.mono,dir="incr") |
|
|
|
} |
|
|
|
|
|
|
|
# calculate adjusted p-values: |
|
|
|
tpvalue <- apply(tPerm.mono>=t.sort, 1, mean, na.rm=TRUE) |
|
|
|
|
|
|
|
# enforce monotonicity on adjusted p-values in tpvalue: |
|
|
|
if(k>1){ tpvalue <- impose.mono(tpvalue, dir="decr") } |
|
|
|
|
|
|
|
list(tstat=t, tadjp=tpvalue[order(index)]) |
|
|
|
} |
|
|
|
|
|
|
|
### |
|
|
|
elsdfreq <- function(data, nExp, nCtl, nameCtl, alpha=0.05){ |
|
|
|
data <- as.data.frame(data) |
|
|
|
data <- data[order(data[,1],data[,2]),] |
|
|
|
ncdat <- data[data[,3]==nameCtl,] |
|
|
|
dat <- data.frame(matrix(NA,nrow=NROW(data[data[,3]!=nameCtl,]),ncol=3+nExp+nCtl)) |
|
|
|
dat[,1:(3+nExp)] <- data[data[,3]!=nameCtl,] |
|
|
|
names(dat) <- c(names(data)[1:(3+nExp)],paste("c",1:nCtl,sep="")) |
|
|
|
for(id in unique(data[,1])){ |
|
|
|
for(day in unique(data[,2])){ |
|
|
|
dat[dat[,1]==id & dat[,2]==day,3+nExp+(1:nCtl)] <- ncdat[ncdat[,1]==id & ncdat[,2]==day,-(1:3)] |
|
|
|
}} |
|
|
|
|
|
|
|
### dat = a data.frame with ptid, day, antigen in cols 1 to 3, |
|
|
|
### peptide replicates in col4:(3+nExp), control replicates in |
|
|
|
### col(4+nExp):col(3+nExp+nCtl) |
|
|
|
### Same control replicates are repeated for each peptide per unique ptid |
|
|
|
|
|
|
|
### nExp = no. of experimental wells per peptide |
|
|
|
### nCtl = no. of negative control wells |
|
|
|
### Use alpha=0.05 as default |
|
|
|
|
|
|
|
ind <- unique(dat[,1:2]) |
|
|
|
adjp <- teststat <- pos.call <- NULL |
|
|
|
|
|
|
|
# perform permutation test on each unique ptid*day combination with |
|
|
|
# multiplicity adjustment for the number of peptide pools |
|
|
|
|
|
|
|
for(i in 1:NROW(ind)){ |
|
|
|
temp.dat <- as.matrix(dat[dat[,1]==ind[i,1] & dat[,2]==ind[i,2],-(1:3)]) |
|
|
|
temp.id <- ind[i,1] |
|
|
|
temp.day <- ind[i,2] |
|
|
|
temp.pep <- dat[dat[,1]==ind[i,1] & dat[,2]==ind[i,2],3] |
|
|
|
if (length(temp.pep)==1) temp.dat <- t(temp.dat) |
|
|
|
temp.adjp <- temp.teststat <- rep(NA, NROW(temp.dat)) |
|
|
|
|
|
|
|
nas <- is.na(temp.dat) |
|
|
|
nCtlc <- nCtl - sum(nas[1,nExp+(1:nCtl)]) # observed number of neg ctl reps |
|
|
|
nExpC <- nExp - apply(nas[,1:nExp],1,sum) # observed numbers of exp reps |
|
|
|
idx <- (nExpC>=3 & nCtlc>=3) | (nExpC>=2 & nCtlc>=4) |
|
|
|
if (sum(idx)>0){ |
|
|
|
temp.dat <- as.matrix(temp.dat[idx,]) |
|
|
|
if (sum(idx)==1 & length(idx)>1){ |
|
|
|
temp.dat <- t(temp.dat) |
|
|
|
out<-perm(dat=rbind(temp.dat,temp.dat), nExp=nExp, nCtl=nCtl) |
|
|
|
out<-lapply(out, function(x) x[1]) |
|
|
|
}else{ |
|
|
|
out <- perm(dat=temp.dat, nExp=nExp, nCtl=nCtl) |
|
|
|
} |
|
|
|
|
|
|
|
temp.teststat[idx] <- out$tstat |
|
|
|
temp.adjp[idx] <- out$tadjp |
|
|
|
} |
|
|
|
teststat <- c(teststat, temp.teststat) |
|
|
|
adjp <- c(adjp, temp.adjp) |
|
|
|
|
|
|
|
if (nCtlc<nCtl) warning(paste("ptid", temp.id, "has", nCtl-nCtlc, "missing value(s) for negative controls", "on day", temp.day)) |
|
|
|
if (min(nExpC)<nExp){ |
|
|
|
for (j in 1:sum(nExpC<nExp)){ |
|
|
|
warning(paste("ptid", temp.id, "has", nExp-nExpC[nExpC<nExp][j], "missing value(s) for", temp.pep[nExpC<nExp][j], "on day", temp.day)) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
pos.call <- ifelse(adjp <= alpha,1,0) |
|
|
|
|
|
|
|
output <- data.frame(cbind(dat,round(teststat,5),round(adjp,5),pos.call)) |
|
|
|
colnames(output)[(ncol(dat)+1):(ncol(dat)+3)] <- c("t-stat","adjp","pos") |
|
|
|
output |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#### Read (excel or csv) and create "data" |
|
|
|
# library(readxl) |
|
|
|
# data<-read_xlsx("C:/Users/y2955361j/Downloads/example.xlsx") |
|
|
|
# |
|
|
|
# ## elsdfreq <- function(data, nExp, nCtl, nameCtl, alpha=0.05 |
|
|
|
# ### nExp = no. of experimental wells per peptide (usually 3) |
|
|
|
# ### nCtl = no. of negative control wells (usually 6) |
|
|
|
# ### Use alpha=0.05 as default |
|
|
|
# |
|
|
|
# results<-elsdfreq (data, 3, 6, 'control', alpha=0.05) |
|
|
|
# View(results) |
|
|
|
|