P-values depend on the sampling plan

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 :)