Web-based Supporting information for “Confidence intervals based on some weighting functions for the difference of two binomial proportions” by K. Maruo PhD and N. Kawai PhD. Description about R function “riskdif_ci_weight” for calculating proposed CI estimation methods (NewL and NewB) Usage riskdif_ci_weight (n1, n2, x1, x2, alpha, weight) Arguments n1: sample size of group1 n2: sample size of group2, x1: number of event for group 1 x2: number of event for group 2, alpha: 100(1-alpha)% CI weight: 1:likelihood, 2:truncated beta pdf Value Returns 3 x 1 vector: {lower confidence limit, MLE of delta, upper confidence limit} R code ################################################################################ # MLE of p1 and p2 under null hypothesis # (Farrington and Manning(1990), Stat. Med., 9, 1447-1454.) mle_p1_h0<- function(n1,n2,x1,x2,d){ theta <- n2/n1 p1 <- x1/n1 p2 <- x2/n2 a1 <- 1+theta a2 <- -(1+theta+p1+theta*p2+d*(theta+2)) a3 <- d^2+d*(2*p1+theta+1)+p1+theta*p2 a4 <- -p1*d*(1+d) v <- a2^3/(3*a1)^3-a2*a3/(6*a1^2)+a4/(2*a1) u <- sign(v)*sqrt(a2^2/(3*a1)^2-a3/(3*a1))+1e-10 uv <- v/u^3 uv[uv < -1] <- -1 uv[uv > 1] <- 1 uv[u-1e-10 == 0] <- 0 w <- (pi+acos(uv))/3 p1t <- 2*u*cos(w)-a2/(3*a1) p1t[p1t<0] <- 0 p1t[p1t>1] <- 1 p2t <- p1t-d p2t[p2t<0] <- 0 p2t[p2t>1] <- 1 return(list(p1t,p2t)) } mle_se_h0<- function(n1,n2,x1,x2,d){ n0 <- matrix(0,length(x1),length(x2)) p12 <- mle_p1_h0(n0+n1,n0+n2,t(numeric(length(x2))+1)%x%x1, (numeric(length(x1))+1)%x%t(x2),d) se<- sqrt(p12[[1]]*(1-p12[[1]])/n1+p12[[2]]*(1-p12[[2]])/n2) if (abs(d)==1) se[,] <- 0 if (length(x1)==1|length(x2)==1) se <- c(se) return(se) } #----------------------------------------------------------------------------- # CI for risk difference (Maruo and Kawai's method)-----------riskdif_ci_weight<-function(n1,n2,x1,x2,alpha,weight){ # CI for risk difference (Quasi exact methods based on weight functions) # n1:sample size of group1, n2:sample size of group2, # x1:number of event for group 1, x2:number of event for group 2, # alpha: 100(1-alpha)% CI, # weight: 1:likelihood, 2:truncated beta pdf if (alpha <= 0|alpha>=1) stop('alpha is not given appropriately!') if (x1>n1) stop('x1 must be equal to or lower than n1!') if (x2>n2) stop('x2 must be equal to or lower than n2!') if (weight!=1 & weight!=2) stop('weight must be 1(likelihood) or 2(truncated beta pdf)!') if (x1<0|x2<0|abs(x1-as.integer(x1))>1e-10|abs(x2-as.integer(x2))>1e-10){ stop('x1 and x2 must be non-negative integer!') } if (n1<=0|n2<=0|abs(n1-as.integer(n1))>1e-10|abs(n2-as.integer(n2))>1e-10){ stop('n1 and n2 must be positive integer!') } if (n1>50|n2>50) print('n1 and/or n2 are large number. Calculation time may be long.') dig <- 3 prec <- 1e-3 # precision of estimation flg <- 0 if (n1<n2){ # for symmetry property of CI n3 <- n1 x3 <- x1 n1 <- n2 x1 <- x2 n2 <- n3 x2 <- x3 flg <- 1 } Y1 <- 0:n1 Y2 <- 0:n2 on1 <- numeric(n1+1)+1 on2 <- numeric(n2+1)+1 cy1 <- choose(n1,Y1) cy2 <- choose(n2,Y2) cx1 <- choose(n1,x1) cx2 <- choose(n2,x2) # calculation of (p-value - alpha/2)^2 for given delta(d) prob_d <- function(d,up){ if (abs(d)==1){ s <- ((t(on2)%x%(Y1/n1))-(on1%x%t(Y2/n2))-d) st <- (x1/n1-x2/n2-d) } else { s <- ((t(on2)%x%(Y1/n1))-(on1%x%t(Y2/n2))-d)/(mle_se_h0(n1,n2,Y1,Y2,d)) st <- (x1/n1-x2/n2-d)/(mle_se_h0(n1,n2,x1,x2,d)) } p12t <- mle_p1_h0(n1,n2,x1,x2,d) # calculation of tail probability for given P and delta(d) prob_p_d <- function(p){ ps<-numeric(length(p)) for (ip in 1:length(p)){ pn1 <- cy1*p[ip]^Y1*(1-p[ip])^(n1-Y1) pn2 <- cy2*(p[ip]-d)^Y2*(1+d-p[ip])^(n2-Y2) prob <- (t(on2)%x%pn1)*(on1%x%t(pn2)) if (up==1) ps[ip] <- sum((s<=st)*prob) else ps[ip] <- sum((s>=st)*prob) } return(ps) } # weighted p-value based on likelihood if (weight==1){ lik_wgt <- function(p){ p2=p-d return(cx1*p^x1*(1-p)^(n1-x1)*cx2*p2^x2*(1-p2)^(n2-x2)) } p_lik_wgt <- function(p){ return(prob_p_d(p)*lik_wgt(p)) } par <- prob_p_d(min(c(1,1+d))) if (min(c(1,1+d))-max(c(0,d))>1e-10){ par1 <- integrate(p_lik_wgt,max(c(0,d)),min(c(1,1+d)))$value par2 <- integrate(lik_wgt,max(c(0,d)),min(c(1,1+d)))$value par <- par1/par2 } } # weighted p-value based on truncated beta pdf if (weight==2) { p_beta_wgt <- function(p){ return(prob_p_d(p)*dbeta(p,n1*p12t[[1]]+1,n1*(1-p12t[[1]])+1)) } par <- prob_p_d(min(c(1,1+d))) if (min(c(1,1+d))-max(c(0,d))>1e-10){ par1 <- integrate(p_beta_wgt,max(c(0,d)),min(c(1,1+d)))$value par2 <- pbeta(min(c(1,1+d)),n1*p12t[[1]]+1,n1*(1-p12t[[1]])+1)pbeta(max(c(0,d)),n1*p12t[[1]]+1,n1*(1-p12t[[1]])+1) par <- par1/par2 } } return((par-alpha/2)^2) } dobs <- x1/n1-x2/n2 # optimization process based on grid search opt2 <- function(up){ if (up==1) d0 <- seq(dobs,1,by=prec*50) else d0 <- seq(-1,dobs,by=prec*50) cl0 <- numeric(length(d0)) j <- 1 for (d0i in d0){ cl0[j] <- prob_d(d0i,up) j <- j+1 } m0 <- which.min(cl0) if (up==1) d1 <- seq(min(d0[max(m0-1,1)],dobs),max(d0[min(m0+1,length(d0))],1),by=prec*10) else d1 <- seq(min(d0[max(m0-1,1)],-1),max(d0[min(m0+1,length(d0))],dobs),by=prec*10) cl1 <- numeric(length(d1)) j <- 1 for (d1i in d1){ cl1[j] <- prob_d(d1i,up) j <- j+1 } m1 <- which.min(cl1) if (up==1) d2 <- seq(min(d1[max(m1-1,1)],dobs),max(d1[min(m1+1,length(d1))],1),by=prec) else d2 <- seq(min(d1[max(m1-1,1)],-1),max(d1[min(m1+1,length(d1))],dobs),by=prec) cl2 <- numeric(length(d2)) j <- 1 for (d2i in d2){ cl2[j] <- prob_d(d2i,up) j <- j+1 } cl3 <- d2[which.min(cl2)] return(cl3) } # calculation of CI for delta lower <- -1 if (dobs != -1) lower <- opt2(0) upper <- 1 if (dobs != 1) upper <- opt2(1) if (flg==1){ dum <- lower lower <- -upper upper <- -dum dobs <- -dobs } dobs <- round(dobs, digits = dig) lower <- round(lower, digits = dig) upper <- round(upper, digits = dig) return(c(lower,dobs,upper)) } #-----------------------------------------------------------------------# ECOG data analysis based on Maruo and Kawai's methods riskdif_ci_weight(14,11,2,1,0.1,1)#New likelihood weighting method riskdif_ci_weight(14,11,2,1,0.1,2)#Beta weighting method ####################################################################################