An interactive 2-sided p-value test of a proportion using the shiny package in R
The 2-sided test of a proportion ‘theta’ can be written as
- H0: theta = theta0 (i.e., the proportion is equal to a null value)
- H1: theta != theta0 (i.e., the proportion is unequal to a null value)
The shiny app computes the 2-tailed p-value for this test based on a binomial sampling plan (i.e., perform a certain experiment N number of times out of which we observe x successes) and a negative binomial sampling plan (i.e., conduct an experiment until x successes have been observed for which we needed N number of experiments in total).
- Install R.
- Install Rstudio.
- Via Tools -> install packages -> shiny.
- In the console, write: “library(shiny)”.
- Create folder named “P-value sampling plan”.
- Create a R-script file in Rstudio and call the file: ui.R.
- Save ui.R in the folder “P-value sampling plan”.
- Create a R-script file in Rstudio called: server.R.
- Save server.R in the folder “P-value sampling plan”.
- Paste the syntax below to ui.R. (scroll down for the next step).
#astro posterior library(shiny) shinyUI(fluidPage( # Application title titlePanel("Classical test of H0: theta=.5 versus H1: theta!=.5"), # Sidebar with a slider input sidebarLayout( sidebarPanel( sliderInput("nobs", "Number of experiments:", min = 1, max = 100, value=60), sliderInput("ncorrect", "Number of correct answers:", min = 1, max = 100, value = 38), sliderInput("theta0", "H0:theta=", min = .001, max = .99, value = .5) # checkboxInput("pvalue", "View 2-sided p-value",F) ), # Show a plot of the generated distribution mainPanel( plotOutput("distPlot1"), textOutput("pvalue1"), plotOutput("distPlot2"), textOutput("pvalue2") ) ) ))
- Paste the syntax below to server.R. (scroll down for the final step).
library(shiny) shinyServer(function(input, output) { output$distPlot1 = renderPlot({ theta0 = input$theta0 N = input$nobs x = input$ncorrect xright = x if(xN/2){xleft=N-x} probs = dbinom(0:N,size=N,prob=theta0) pvalue1 = sum(probs[1:(xleft+1)]) paste("The p-value is ",round(pvalue1*2,3)) text(x=xleft+2,y=max(probs)/10,round(pvalue1,3),pos=2) text(x=xright+10,y=max(probs)/10,round(pvalue1,3),pos=4) }) output$pvalue1 N/2){xleft=N-x} probs = dbinom(0:N,size=N,prob=input$theta0) pvalue1 = sum(probs[1:(xleft+1)]) paste0("The p-value is ",round(pvalue1*2,3),".") }) output$distPlot2 = renderPlot({ dnegbinom = function(n,xx,prob){ #stop until x successes. total number of experiments is n. #prob is probability of success per experiment exp(xx*log(prob)+(n-xx)*log(1-prob)+lfactorial(n-1)-lfactorial(xx-1)-lfactorial(n-xx)) } theta0 = input$theta0 N = input$nobs x = input$ncorrect maxx = x/theta0*2 probs = dnegbinom(n=x:maxx,x=x,prob=theta0) barplot(probs,names.arg=x:maxx,xlim=c(0,maxx),ylim=c(0,max(probs))) if(x/N>theta0){ par(new=T) #at least as extreme as N is N and less barplot(c(probs[1:(N-x+1)],rep(0,maxx-N+x)),xlim=c(0,maxx),ylim=c(0,max(probs)),col=2) pleft = sum(probs[1:(N-x+1)]) text(N-x-8,max(probs)/10,round(pleft,3)) pxleft = 1-x/N for(nn in (N+1):maxx){ if(x/nn<=pxleft){ Nright = nn break } } par(new=T) #at least as extreme as N is Nleft and more barplot(c(rep(0,(Nright-x)),probs[(Nright-x+1):(maxx-x+1)]),xlim=c(0,maxx),ylim=c(0,max(probs)),col=2) pright = sum(probs[(Nright-x+1):(maxx-x+1)]) text(N+x,max(probs)/10,round(pright,3)) } if(x/N<theta0){ par(new=T) barplot(c(rep(0,(N-x-1)),probs[(N-x):(maxx-x+1)]),xlim=c(0,maxx),ylim=c(0,max(probs)),col=2) pright = sum(probs[(N-x):(maxx-x+1)]) text(N+x,max(probs)/10,round(pright,3)) pxright = 1-x/N for(nn in (x+1):N){ if(x/nn<=pxright){ Nleft = nn-1 break } } par(new=T) barplot(c(probs[1:(Nleft-x)],rep(0,maxx-Nleft+x)),xlim=c(0,maxx),ylim=c(0,max(probs)),col=2) pleft = sum(probs[1:(Nleft-x)]) text(N-x-18,max(probs)/10,round(pleft,3)) } }) output$pvalue2 theta0){ # par(new=T) #at least as extreme as N is N and less # barplot(c(probs[1:(N-x+1)],rep(0,maxx-N+x)),xlim=c(0,maxx),ylim=c(0,max(probs)),col=2) pleft = sum(probs[1:(N-x+1)]) # text(N-x-8,max(probs)/10,round(pleft,3)) pxleft = 1-x/N for(nn in (N+1):maxx){ if(x/nn<=pxleft){ Nright = nn break } } # par(new=T) #at least as extreme as N is Nleft and more # barplot(c(rep(0,(Nright-x)),probs[(Nright-x+1):(maxx-x+1)]),xlim=c(0,maxx),ylim=c(0,max(probs)),col=2) pright = sum(probs[(Nright-x+1):(maxx-x+1)]) # text(N+x,max(probs)/10,round(pright,3)) pvalue2 = pleft+pright } if(x/N<theta0){ # par(new=T) # barplot(c(rep(0,(N-x-1)),probs[(N-x):(maxx-x+1)]),xlim=c(0,maxx),ylim=c(0,max(probs)),col=2) pright = sum(probs[(N-x):(maxx-x+1)]) # text(N+x,max(probs)/10,round(pright,3)) pxright = 1-x/N for(nn in (x+1):N){ if(x/nn<=pxright){ Nleft = nn-1 break } } par(new=T) # barplot(c(probs[1:(Nleft-x)],rep(0,maxx-Nleft+x)),xlim=c(0,maxx),ylim=c(0,max(probs)),col=2) pleft = sum(probs[1:(Nleft-x)]) # text(N-x-18,max(probs)/10,round(pleft,3)) pvalue2 = pleft+pright } paste0("The p-value is ",round(pvalue2,3),".") }) })
- Press “Run App” in Rstudio. Enjoy :)