In the previous article entitled Statistical Distribution and Its Density Plot Shiny Application – Part 1, we learned how to draw the graph of the density function of a distribution by generating random numbers from that distribution. In this article, we will solve the disadvantages and problems that existed in the previous program and provide the possibility of Compare Statistical Distributions by density plot.
We mentioned that if the parameters selected by the user do not match the statistical distribution, the previous program would not report an error, but it would not be able to draw the statistical distribution graph either. In this section, we want to fix this problem and if the user parameter does not match the set of parameter values, an error message will appear. On the other hand, to compare two statistical distributions, we also want to draw two overlapped graphs of the density function of both distributions. We will also use a list to select each distribution. The choice of color as well as the parameters of each distribution will be specified in this section of the article. Remember that we will do this using the shiny library.
Compare Statistical Distributions by Density Plot
Part 1
First of all, a library (shinyalert) is added to the program for handling errors of out-of-range parameters.
1 2 3 4 5 |
# Load the required libraries library(shiny) library(ggplot2) <strong>library(shinyalert)</strong> library(colourpicker) |
Part 2
Now, some codes are added to recognized errors and alarm the user. This part must lay down on server part. beware that these functions are related to shinyalert library.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
observeEvent(input$goButton, { error_handler = "The Parameters Do not match for this Distribution" if (input$dist1 == "Uniform" && input$dist1_b <= input$dist1_a ) { shinyalert(error_handler,size = "xs") return(NULL) } if (input$dist1 == "Uniform" && input$dist2_b <= input$dist2_a ) { shinyalert(error_handler,size="xs") return(NULL) } }) } |
Part 3
Other parameters (such as normal or F distributions) values are check by their values limitation. such as the code below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
output$dist2_params <- renderUI({ if (input$dist2 == "Normal") { list( numericInput("dist2_mean", "Mean:", value = 0), numericInput("dist2_sd", "Standard Deviation:",min=0.1, value = 1) ) } else if (input$dist2 == "t") { list( numericInput("dist2_df", "Degrees of Freedom:", min=1,value = 3) ) } else if (input$dist2 == "Chi-Squared") { list( numericInput("dist2_df", "Degrees of Freedom:",min=1, value = 3) ) } else if (input$dist2 == "F") { list( numericInput("dist2_df1","Degrees of Freedom:",min=1,value = 3), numericInput("dist2_df2","Degrees of Freedom:",min=1,value = 3) ) } else { list( numericInput("dist2_a", "Lower Limit:", min=0,value = 0), numericInput("dist2_b", "Upper Limit:", min=0,value = 1) ) } }) |
Compare statistical distributions by density plot must ensure that all parameters are suitable and compatible for that distribution.
The min value controls the minimum value to the parameter and value shows its default value.
Part 4
The GUI interface to show two distributions and their parameters are in the part 4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
# Generate the distribution parameters UI output$dist1_params <- renderUI({ if (input$dist1 == "Normal") { list( numericInput("dist1_mean", "Mean:", value = 0), numericInput("dist1_sd", "Standard Deviation:",min=0.1, value = 1) ) } else if (input$dist1 == "t") { list( numericInput("dist1_df", "Degrees of Freedom:", min=1,value = 3) ) } else if (input$dist1 == "Chi-Squared") { list( numericInput("dist1_df", "Degrees of Freedom:",min=1, value = 3) ) } else if (input$dist1 == "F" ) { list( numericInput("dist1_df1", "Degrees of Freedom 1:",min=1, value = 3), numericInput("dist1_df2", "Degrees of Freedom 2:", min=1,value = 3) ) } else{ list( numericInput("dist1_a","Lower limit",min=0,value = 0), numericInput("dist1_b","Upper Limit",min=0,value = 1) ) } }) |
Even if you change the order of each part of codes, the result will not change.
Part 5
Notice that some changes must be done in UI layer for comparing two distributions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# Define the UI ui <- fluidPage( titlePanel("Compare Two Distributions"), sidebarLayout( sidebarPanel( helpText("This app compares two statistical distributions."), numericInput("n", "Number of Observations:", value = 100), selectInput("dist1", "Distribution 1:", choices = c("Normal", "t", "Chi-Squared", "F","Uniform"),selected="Normal"), uiOutput("dist1_params"), colourpicker::colourInput("dist1_color", "Color for Distribution 1:",closeOnClick=TRUE , returnName=TRUE,palette = 'limited', value = "red"), selectInput("dist2", "Distribution 2:", choices = c("Normal", "t", "Chi-Squared", "F","Uniform"),selected="Normal"), uiOutput("dist2_params"), colourpicker::colourInput("dist2_color", "Color for Distribution 2:",closeOnClick=TRUE,returnName=TRUE ,palette='limited', value = "blue"), actionButton("goButton", "Compare!") ), mainPanel( plotOutput("distPlot") ) ) ) # Define the server server <- function(input, output) { # Generate the data data <- reactive({ dist1 <- switch(input$dist1, "Normal" = rnorm(input$n, mean = input$dist1_mean, sd = input$dist1_sd), "t" = rt(input$n, df = input$dist1_df), "Chi-Squared" = rchisq(input$n, df = input$dist1_df), "F" = rf(input$n, df1 = input$dist1_df1, df2 = input$dist1_df2), "Uniform"=runif(input$n,input$dist1_a,max=input$dist1_b)) dist2 <- switch(input$dist2, "Normal" = rnorm(input$n, mean = input$dist2_mean, sd = input$dist2_sd), "t" = rt(input$n, df = input$dist2_df), "Chi-Squared" = rchisq(input$n, df = input$dist2_df), "F" = rf(input$n, df1 = input$dist2_df1, df2 = input$dist2_df2), "Uniform"=runif(input$n,input$dist2_a,max=input$dist2_b)) data.frame(Distribution = rep(c("Distribution 1", "Distribution 2"), each = input$n), Value = c(dist1, dist2)) }) output$distPlot <- renderPlot({ # Define the colors for each distribution dist1_color <- input$dist1_color dist2_color <- input$dist2_color # Generate the plot ggplot(data(), aes(x = Value, fill = Distribution)) + geom_density(alpha = 0.5) + scale_fill_manual(values = c(dist1_color, dist2_color)) + labs(title = "Compare Two Distributions", x = "Value", y = "Density") + theme(plot.title = element_text(hjust = 0.5)) }) |
Part 6
Ruuning code and show the interface is located in this part.
1 2 |
# Run the app shinyApp(ui = ui, server = server) |
Whole code and orders of procedures
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# Load the required libraries library(shiny) library(ggplot2) library(shinyalert) library(shinyjs) library(colourpicker) # Define the UI ui <- fluidPage( titlePanel("Compare Two Distributions"), sidebarLayout( sidebarPanel( helpText("This app compares two statistical distributions."), numericInput("n", "Number of Observations:", value = 100), selectInput("dist1", "Distribution 1:", choices = c("Normal", "t", "Chi-Squared", "F","Uniform"),selected="Normal"), uiOutput("dist1_params"), colourpicker::colourInput("dist1_color", "Color for Distribution 1:",closeOnClick=TRUE , returnName=TRUE,palette = 'limited', value = "red"), selectInput("dist2", "Distribution 2:", choices = c("Normal", "t", "Chi-Squared", "F","Uniform"),selected="Normal"), uiOutput("dist2_params"), colourpicker::colourInput("dist2_color", "Color for Distribution 2:",closeOnClick=TRUE,returnName=TRUE ,palette='limited', value = "blue"), actionButton("goButton", "Compare!") ), mainPanel( plotOutput("distPlot") ) ) ) # Define the server server <- function(input, output) { # Generate the data data <- reactive({ dist1 <- switch(input$dist1, "Normal" = rnorm(input$n, mean = input$dist1_mean, sd = input$dist1_sd), "t" = rt(input$n, df = input$dist1_df), "Chi-Squared" = rchisq(input$n, df = input$dist1_df), "F" = rf(input$n, df1 = input$dist1_df1, df2 = input$dist1_df2), "Uniform"=runif(input$n,input$dist1_a,max=input$dist1_b)) dist2 <- switch(input$dist2, "Normal" = rnorm(input$n, mean = input$dist2_mean, sd = input$dist2_sd), "t" = rt(input$n, df = input$dist2_df), "Chi-Squared" = rchisq(input$n, df = input$dist2_df), "F" = rf(input$n, df1 = input$dist2_df1, df2 = input$dist2_df2), "Uniform"=runif(input$n,input$dist2_a,max=input$dist2_b)) data.frame(Distribution = rep(c("Distribution 1", "Distribution 2"), each = input$n), Value = c(dist1, dist2)) }) output$distPlot <- renderPlot({ # Define the colors for each distribution dist1_color <- input$dist1_color dist2_color <- input$dist2_color # Generate the plot ggplot(data(), aes(x = Value, fill = Distribution)) + geom_density(alpha = 0.5) + scale_fill_manual(values = c(dist1_color, dist2_color)) + labs(title = "Compare Two Distributions", x = "Value", y = "Density") + theme(plot.title = element_text(hjust = 0.5)) }) # Generate the distribution parameters UI output$dist1_params <- renderUI({ if (input$dist1 == "Normal") { list( numericInput("dist1_mean", "Mean:", value = 0), numericInput("dist1_sd", "Standard Deviation:",min=0.1, value = 1) ) } else if (input$dist1 == "t") { list( numericInput("dist1_df", "Degrees of Freedom:", min=1,value = 3) ) } else if (input$dist1 == "Chi-Squared") { list( numericInput("dist1_df", "Degrees of Freedom:",min=1, value = 3) ) } else if (input$dist1 == "F" ) { list( numericInput("dist1_df1", "Degrees of Freedom 1:",min=1, value = 3), numericInput("dist1_df2", "Degrees of Freedom 2:", min=1,value = 3) ) } else{ list( numericInput("dist1_a","Lower limit",min=0,value = 0), numericInput("dist1_b","Upper Limit",min=0,value = 1) ) } }) output$dist2_params <- renderUI({ if (input$dist2 == "Normal") { list( numericInput("dist2_mean", "Mean:", value = 0), numericInput("dist2_sd", "Standard Deviation:",min=0.1, value = 1) ) } else if (input$dist2 == "t") { list( numericInput("dist2_df", "Degrees of Freedom:", min=1,value = 3) ) } else if (input$dist2 == "Chi-Squared") { list( numericInput("dist2_df", "Degrees of Freedom:",min=1, value = 3) ) } else if (input$dist2 == "F") { list( numericInput("dist2_df1","Degrees of Freedom:",min=1,value = 3), numericInput("dist2_df2","Degrees of Freedom:",min=1,value = 3) ) } else { list( numericInput("dist2_a", "Lower Limit:", min=0,value = 0), numericInput("dist2_b", "Upper Limit:", min=0,value = 1) ) } }) observeEvent(input$goButton, { error_handler = "The Parameters Do not match for this Distribution" if (input$dist1 == "Uniform" && input$dist1_b <= input$dist1_a ) { shinyalert(error_handler,size = "xs") return(NULL) } if (input$dist1 == "Uniform" && input$dist2_b <= input$dist2_a ) { shinyalert(error_handler,size="xs") return(NULL) } }) } # Run the app shinyApp(ui = ui, server = server) |
The result is something like window as picture below.
Compare Statistical Distributions by Density Plot| A Shiny Application