Jazz up a simple shiny app to look at my data

Hello!
I am making a shiny app so I can look through my data easily. I have made one and it works, but it's my first and it could definitely be better looking and more efficient.

My objective is to have three dropdown lists with the same markers, allowing me to select three different markers and display the associated box plots and ANOVA results.

Currently, if you run my code, the graphs are stacked vertically. I'd prefer to organize them in a grid, which I find more visually appealing and easier to interpret in conjunction with the ANOVA results. It would also stop me having to scroll up to the menu to change the drop down, and have it all in a single visual page

Also, it would be great to visually distinguish the dropdown lists based on whether the selected prefix is "cat," "dog," or "rabbit."

Lastly, instead of having a line underneath the graph, I'd like to include a subtitle on each graph with the ANOVA results.

Totally open to any and all suggestions, and I know my code is mega repetitive...
Thank you!!

# Load Packages
library(shiny)
library(dplyr)
library(ggplot2)
library(stringr)
library(lme4)
library(lmerTest)


# Create a data frame
fulldf <- data.frame(
  ID = rep(1:100, each = 4),  # Repeat each ID four times
  dog_weight_raw = runif(400, min = 5, max = 30),
  dog_size_raw = runif(400, min = 10, max = 50),
  dog_width_raw = runif(400, min = 5, max = 20),
  cat_whiskers_raw = runif(400, min = 0, max = 10),
  cat_length_raw = runif(400, min = 20, max = 60),
  cat_weight_raw = runif(400, min = 2, max = 8),
  cat_class_raw = runif(400, min = 20, max = 80),
  cat_breed_log10 = runif(400, min = 2, max = 8),
  cat_size_log10 = runif(400, min = 54, max = 200),
  rabbit_height_log10 = runif(400, min = 10, max = 30),
  rabbit_length_log10 = runif(400, min = 15, max = 40),
  timepoint = rep(1:4, each = 100)  # Repeat timepoints 1, 2, 3, 4 for all IDs
)
fulldf$timepoint<-as.factor(fulldf$timepoint)


# make a marker list

markers <- names(df)[grep("log10$|_raw$", names(df))]
# sort markers
markers <- sort(markers)






######################################### UI #############################################
ui <- fluidPage(
  titlePanel("Marker Boxplots"), #Sets the title of the Shiny app
  
  
  sidebarLayout(
    sidebarPanel( #Sidebar inputs
      selectInput(
        inputId = "markerselect1",  # ID of the first selectInput
        label = "Select a marker:",  # Label for the first selectInput
        choices = markers,  # Choices for the first selectInput
        selected = NULL  # Initial selected value for the first selectInput
      ),
      selectInput(
        inputId = "markerselect2",  # ID of the second selectInput
        label = "Select a column:",  # Label for the second selectInput
        choices = markers,  # Choices for the second selectInput
        selected = NULL  # Initial selected value for the second selectInput
      ),
      selectInput(
        inputId = "markerselect3",  # ID of the third selectInput
        label = "Select a column:",  # Label for the third selectInput
        choices = markers,  # Choices for the third selectInput
        selected = NULL  # Initial selected value for the third selectInput
      ),
      width = 3 #Width of the sidebar panel
    ),
    
    mainPanel(  # Contains the main panel outputs
      plotOutput(outputId = "marker1_boxplot"),  
      textOutput(outputId = "marker1_anova_result"),  
      plotOutput(outputId = "marker2_boxplot"),  
      textOutput(outputId = "marker2_anova_result"),  
      plotOutput(outputId = "marker3_boxplot"), 
      textOutput(outputId = "marker3_anova_result")  
    )
  )
)


######################################### SERVER #############################################
server <- function(input, output) {
  # Function to select and filter data and run an ANOVA
  compute_model <- function(df, column_name) {
    
    filtered_df <- df %>%
      select(timepoint, ID, !!sym(column_name)) %>%
      filter(!is.na(.[[column_name]]) & is.finite(.[[column_name]]))  # Filter the data, removing rows with NA or infinite values
    
    # Perform linear mixed-effects regression and calculate ANOVA
    lmer_model <- lmer(formula = as.formula(paste(column_name, "~ timepoint + (1 | ID)")), data = filtered_df)
    anova_result <- anova(lmer_model, type = "III")
    p_value <- formatC(anova_result[["Pr(>F)"]][1], format = "f", digits = 5)  # Format the p-value
    p_value_display <- ifelse(as.numeric(p_value) < 0.05, paste0(p_value, "*"), p_value)  # Add asterisk if p-value is significant
    
    textual_result <- paste("Repeated Measures ANOVA p-value:", p_value_display)
    
    results <- list(
      lmer_model = lmer_model,
      anova_result = anova_result,
      p_value = p_value,
      p_value_display = p_value_display,
      textual_result = textual_result
    )
    
    return(results)
    
  }
  
  # Run the function on marker 1
  output$marker1_anova_result <- renderText({
    selected_marker <- input$markerselect1
    selected_column_name <- paste0(selected_marker)
    model_stuff <- compute_model(fulldf, column_name = selected_column_name)
    return(model_stuff$textual_result)
    
  })
  
  # Run the function on marker 2 
  output$marker2_anova_result <- renderText({
    selected_marker <- input$markerselect2
    selected_column_name <- paste0(selected_marker)
    model_stuff <- compute_model(fulldf, column_name = selected_column_name)
    return(model_stuff$textual_result)
    
  })  
  
  
  
  # Run the function on marker 3
  output$marker3_anova_result <- renderText({
    selected_marker <- input$markerselect3
    selected_column_name <- paste0(selected_marker)
    model_stuff <- compute_model(fulldf, column_name = selected_column_name)
    return(model_stuff$textual_result)
    
  })  
  
  # Function to make boxplot
  
  plot_boxplot <- function(df, column_name) {
    
    ggplot(data = df, aes(x = timepoint, y = .data[[column_name]], color = timepoint)) +
      geom_boxplot() +
      labs(x = "timepoint", y = column_name) +
      theme_classic()
    
  }
  
  # Run boxplot function on marker 1
  output$marker1_boxplot <- renderPlot({
    selected_marker <- input$markerselect1
    selected_column_name <- paste0(selected_marker)
    plot_stuff <- plot_boxplot(fulldf, column_name = selected_column_name)
    print(plot_stuff) 
  })
  
  # Run boxplot function on marker 2
  output$marker2_boxplot <- renderPlot({
    selected_marker <- input$markerselect2
    selected_column_name <- paste0(selected_marker)
    plot_stuff <- plot_boxplot(fulldf, column_name = selected_column_name)
    print(plot_stuff) 
  })
  
  
  # Run boxplot function on marker 3
  output$marker3_boxplot <- renderPlot({
    selected_marker <- input$markerselect3
    selected_column_name <- paste0(selected_marker)
    plot_stuff <- plot_boxplot(fulldf, column_name = selected_column_name)
    print(plot_stuff) 
  })
  
  
}

######################################### Run the app! #############################################


shinyApp(ui = ui, server = server)



This topic was automatically closed 54 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.