I B
2024-Jun-06 00:07 UTC
[R] R Shiny Help - Trouble passing user input columns to emmeans after ANOVA analysis
Hello everybody, I have experience coding with R, but am brand new to R Shiny. I am trying to produce an application that will allow users to upload their own dataset, select columns they want an ANOVA analysis run on, and generate graphs that will allow users to view their results. However, I am getting the following error: *"Argument is of length zero."* Being new to Shiny, I am having trouble passing the user input column to an emmeans argument in order to do a post hoc analysis, and using that information to produce a graph. Can somebody help me with this? *The code for my dataset and application are provided below; copying and pasting directly into R should generate the reproducible example.* In my application, the following columns should be selected after uploading the dataset: - Select response variable: "ndvi" - Select first independent variable: "genotype" - Select second independent variable: "rate" - Select random variable: "rep" For this example, the final two drop-down selections should be: - "Which variable would you like to graph? "genotype" - "Which ANOVA model do you want to graph? "Main effects model" Any help would be great. Thank you so much! Sincerely, Isaac Barnhart, PhD *Here is my dataset:* data <- data.frame(rep c(1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3), genotype c('a','a','a','a','b','b','b','b','c','c','c','c','a','a','a','a','b','b','b','b','c','c','c','c','a','a','a','a','b','b','b','b','c','c','c','c'), rate c('1x','2x','4x','8x','1x','2x','4x','8x','1x','2x','4x','8x','1x','2x','4x','8x','1x','2x','4x','8x','1x','2x','4x','8x','1x','2x','4x','8x','1x','2x','4x','8x','1x','2x','4x','8x'), ndvi c(0.584947811,0.642112121,0.654116902,0.785068313,0.79665163,0.674549249,0.958911611,0.547077528,0.613315552,0.768646411,0.97107949,0.680942649,0.520576242,0.723920266,0.868779972,0.834257732,0.554506685,0.520458208,0.617282262,0.80128067,0.875192693,0.572153151,0.850305042,0.500760522,0.796305833,0.643719779,0.590512435,0.522884966,0.905197544,0.663792758,0.690415735,0.975449466,0.621379163,0.734904647,0.812023395,0.928144532)) *Here is my code:* library(shiny) library(ggplot2) library(tidyverse) library(emmeans) library(DHARMa) library(lme4) ui <- fluidPage( fileInput("file1", "Choose .csv or .xlsx file", accept = c("text/csv", "text/comma-separated-values", ".csv", ".xlsx")), textOutput("data_info"), verbatimTextOutput("data_head"), uiOutput("column_selector_1"), uiOutput("column_selector_2"), uiOutput("column_selector_3"), uiOutput("column_selector_4"), textOutput("dist_info"), plotOutput("dist"), textOutput("str_info"), verbatimTextOutput("selected_columns"), textOutput("two_way_anova"), verbatimTextOutput("model_summary"), textOutput("main_effects"), verbatimTextOutput("model_summary_ME"), textOutput("mod_diagnostic"), plotOutput("diagnostic_plot"), uiOutput("graph"), uiOutput("model_selection"), plotOutput("graph_plot") ) server <- function(input, output, session) { # Open file req(data <- reactive({ infile <- input$file1 if (is.null(infile)) { return(NULL) } read.csv(infile$datapath, header = TRUE) })) # Preview data output$data_info <- renderText({ req(data()) "Preview of the data uploaded:" }) output$data_head <- renderPrint({ req(data()) head(data(), 20) }) # Select response variable output$column_selector_1 <- renderUI({ req(data()) selectInput("column1","Select response variable", choices names(data())) }) # Select first independent variable output$column_selector_2 <- renderUI({ req(data()) selectInput("column2", "Select first independent variable", choices names(data())) }) # Select second independent variable output$column_selector_3 <- renderUI({ req(data()) selectInput("column3", "Select second independent variable", choices names(data())) }) # Select random variable output$column_selector_4 <- renderUI({ req(data()) selectInput("column4", "Select random variable", choices names(data())) }) # Assigning user inputs to correct variables selected_columns <- reactive({ req(data(), input$column1, input$column2, input$column3, input$column4) list( dependent = data()[[input$column1]], independent1 = as.factor(data()[[input$column2]]), independent2 = as.factor(data()[[input$column3]]), random = as.factor(data()[[input$column4]]), # Define column names for later use column1 <- input$column1, column2 <- input$column2, column3 <- input$column3, column4 <- input$column4 ) }) # Instructional text output$dist_info <- renderText({ req(data()) "The graph below shows the shape of response variable distribution" }) # Distribution plot output$dist <- renderPlot({ req(selected_columns()) cols <- selected_columns() plot(density(cols$dependent), main = "Distribution Plot") }) # Instructional text output$str_info <- renderText({ req(data()) "The code below verifies that our data are in the correct structure for ANOVA analyses. All independent variables should be changed to 'Factor'. " }) # Verifies that columns are in the correct structure output$selected_columns <- renderPrint({ cols <- selected_columns() str(cols) }) # Instructional text output$two_way_anova <- renderText({ req(data()) "Two-way ANOVA with interaction" }) # Build ANOVA model with two-way interaction interaction_model <- reactive({ cols <- selected_columns() req(cols) data <- data() data$dep <- cols$dependent data$indep1 <- cols$independent1 data$indep2 <- cols$independent2 data$rand <- cols$random lmer(dep ~ indep1 * indep2 + (1|rand), data = data) }) # Run two-way ANOVA model with interaction output$model_summary <- renderPrint({ req(interaction_model()) Anova(interaction_model(), type = c("III")) }) # Build main effects ANOVA model main_effects_model <- reactive({ cols <- selected_columns() req(cols) data <- data() data$dep <- cols$dependent data$indep1 <- cols$independent1 data$indep2 <- cols$independent2 data$rand <- cols$random lmer(dep ~ indep1 + indep2 + (1|rand), data = data) }) # Instructional text output$main_effects <- renderText({ req(data()) "Two-way ANOVA, main effects" }) # Run two-way main effects model output$model_summary_ME <- renderPrint({ req(main_effects_model()) Anova(main_effects_model(), type = c("III")) }) output$mod_diagnostic <- renderText({ req(main_effects_model()) "Below, the `DHARMa` package is used to check model assumptions. If assumptions are not met, then data transformations may be needed before proceeding." }) output$diagnostic_plot <- renderPlot({ req(interaction_model()) plotQQunif(interaction_model()) }) output$graph <- renderUI({ req(data(), input$column2, input$column3) selectInput("graph", "Which variable would you like to graph?", choices = c(input$column2, input$column3, "interaction")) }) output$model_selection <- renderUI({ req(main_effects_model(), interaction_model()) selectInput("model_selection", "Which ANOVA model do you want to graph?", choices = c("Main effects model", "Interaction model")) }) # Create a reactive expression to store the selected graph variable selected_graph <- reactive({ input$graph }) # Create a reactive expression to store the selected model selected_model <- reactive({ input$model_selection }) # Render the plot based on the selected variables output$graph_plot <- renderPlot({ req(data(), selected_graph(), selected_model()) cols <- selected_columns() if (selected_graph() == cols$column2 | selected_model() == "Main effects model") { # Mean separation: First column mod_means_cotr1 <- emmeans(main_effects_model(), pairwise ~ cols$column2, adjust = 'tukey', type = 'response') mod_means1 <- multcomp::cld(object = mod_means_cotr1$emmeans, LETTERS = "letters") # Graph: First column ggplot(mod_means1, aes_string(x = cols$column2, y = cols_column1))+ geom_bar(stat="identity", width = 0.6, position = "dodge", col "black", fill = "purple3")+ geom_errorbar(aes(ymin = emmean, ymax = emmean + SE), width = 0.3, position = position_dodge(0.6))+ xlab(cols$column2)+ ylab(cols$column1)+ theme(plot.title=element_text(hjust=0.5, size = 20), plot.subtitle = element_text(hjust = 0.5, size = 15), axis.text = element_text(size = 17), axis.title = element_text(size = 20))+ geom_text(aes(label=.group, y=emmean + SE), vjust = -0.9, size = 8) + #ylim(0, 105)+ scale_x_discrete(labels = function(x) str_wrap(x, width = 7)) } }) } shinyApp(ui, server) [[alternative HTML version deleted]]
Bert Gunter
2024-Jun-06 14:49 UTC
[R] R Shiny Help - Trouble passing user input columns to emmeans after ANOVA analysis
Wrong list. Shiny is software from an external provider, POSIT (formerly RStudio) and not part of R, itself. They have a community support site at: https://forum.posit.co/?_gl=1*bh848i*_ga*MTY2NjcwNzQ4LjE3MTYyMzkzODQ.*_ga_2C0WZ1JHG0*MTcxNzY4NTExNi4yLjAuMTcxNzY4NTExNi4wLjAuMA .. Cheers, Bert On Thu, Jun 6, 2024 at 12:09?AM I B <ibarnhart055 at gmail.com> wrote:> Hello everybody, > > I have experience coding with R, but am brand new to R Shiny. I am trying > to produce an application that will allow users to upload their own > dataset, select columns they want an ANOVA analysis run on, and generate > graphs that will allow users to view their results. However, I am getting > the following error: *"Argument is of length zero."* > > Being new to Shiny, I am having trouble passing the user input column to an > emmeans argument in order to do a post hoc analysis, and using that > information to produce a graph. Can somebody help me with this? *The code > for my dataset and application are provided below; copying and pasting > directly into R should generate the reproducible example.* > > In my application, the following columns should be selected after uploading > the dataset: > > - Select response variable: "ndvi" > - Select first independent variable: "genotype" > - Select second independent variable: "rate" > - Select random variable: "rep" > > For this example, the final two drop-down selections should be: > > - "Which variable would you like to graph? "genotype" > - "Which ANOVA model do you want to graph? "Main effects model" > > Any help would be great. Thank you so much! > > Sincerely, > Isaac Barnhart, PhD > > > *Here is my dataset:* > > data <- data.frame(rep > c(1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3), > genotype > > c('a','a','a','a','b','b','b','b','c','c','c','c','a','a','a','a','b','b','b','b','c','c','c','c','a','a','a','a','b','b','b','b','c','c','c','c'), > rate > > c('1x','2x','4x','8x','1x','2x','4x','8x','1x','2x','4x','8x','1x','2x','4x','8x','1x','2x','4x','8x','1x','2x','4x','8x','1x','2x','4x','8x','1x','2x','4x','8x','1x','2x','4x','8x'), > ndvi > > c(0.584947811,0.642112121,0.654116902,0.785068313,0.79665163,0.674549249,0.958911611,0.547077528,0.613315552,0.768646411,0.97107949,0.680942649,0.520576242,0.723920266,0.868779972,0.834257732,0.554506685,0.520458208,0.617282262,0.80128067,0.875192693,0.572153151,0.850305042,0.500760522,0.796305833,0.643719779,0.590512435,0.522884966,0.905197544,0.663792758,0.690415735,0.975449466,0.621379163,0.734904647,0.812023395,0.928144532)) > > > *Here is my code:* > > library(shiny) > library(ggplot2) > library(tidyverse) > library(emmeans) > library(DHARMa) > library(lme4) > > ui <- fluidPage( > fileInput("file1", "Choose .csv or .xlsx file", > accept = c("text/csv", > "text/comma-separated-values", > ".csv", > ".xlsx")), > textOutput("data_info"), > verbatimTextOutput("data_head"), > uiOutput("column_selector_1"), > uiOutput("column_selector_2"), > uiOutput("column_selector_3"), > uiOutput("column_selector_4"), > textOutput("dist_info"), > plotOutput("dist"), > textOutput("str_info"), > verbatimTextOutput("selected_columns"), > textOutput("two_way_anova"), > verbatimTextOutput("model_summary"), > textOutput("main_effects"), > verbatimTextOutput("model_summary_ME"), > textOutput("mod_diagnostic"), > plotOutput("diagnostic_plot"), > uiOutput("graph"), > uiOutput("model_selection"), > plotOutput("graph_plot") > ) > > server <- function(input, output, session) { > # Open file > req(data <- reactive({ > infile <- input$file1 > if (is.null(infile)) { > return(NULL) > } > read.csv(infile$datapath, header = TRUE) > })) > > # Preview data > output$data_info <- renderText({ > req(data()) > "Preview of the data uploaded:" > }) > > output$data_head <- renderPrint({ > req(data()) > head(data(), 20) > }) > > # Select response variable > output$column_selector_1 <- renderUI({ > req(data()) > selectInput("column1","Select response variable", choices > names(data())) > }) > > # Select first independent variable > output$column_selector_2 <- renderUI({ > req(data()) > selectInput("column2", "Select first independent variable", choices > names(data())) > }) > > # Select second independent variable > output$column_selector_3 <- renderUI({ > req(data()) > selectInput("column3", "Select second independent variable", choices > names(data())) > }) > > # Select random variable > output$column_selector_4 <- renderUI({ > req(data()) > selectInput("column4", "Select random variable", choices > names(data())) > }) > > # Assigning user inputs to correct variables > selected_columns <- reactive({ > req(data(), input$column1, input$column2, input$column3, input$column4) > list( > dependent = data()[[input$column1]], > independent1 = as.factor(data()[[input$column2]]), > independent2 = as.factor(data()[[input$column3]]), > random = as.factor(data()[[input$column4]]), > > # Define column names for later use > column1 <- input$column1, > column2 <- input$column2, > column3 <- input$column3, > column4 <- input$column4 > ) > }) > > # Instructional text > output$dist_info <- renderText({ > req(data()) > "The graph below shows the shape of response variable distribution" > }) > > > # Distribution plot > output$dist <- renderPlot({ > req(selected_columns()) > cols <- selected_columns() > plot(density(cols$dependent), main = "Distribution Plot") > }) > > # Instructional text > output$str_info <- renderText({ > req(data()) > "The code below verifies that our data are in the correct structure for > ANOVA analyses. All independent variables should be changed to 'Factor'. " > }) > > # Verifies that columns are in the correct structure > output$selected_columns <- renderPrint({ > cols <- selected_columns() > str(cols) > }) > > # Instructional text > output$two_way_anova <- renderText({ > req(data()) > "Two-way ANOVA with interaction" > }) > > # Build ANOVA model with two-way interaction > interaction_model <- reactive({ > cols <- selected_columns() > req(cols) > data <- data() > data$dep <- cols$dependent > data$indep1 <- cols$independent1 > data$indep2 <- cols$independent2 > data$rand <- cols$random > lmer(dep ~ indep1 * indep2 + (1|rand), data = data) > }) > > # Run two-way ANOVA model with interaction > output$model_summary <- renderPrint({ > req(interaction_model()) > Anova(interaction_model(), type = c("III")) > }) > > # Build main effects ANOVA model > main_effects_model <- reactive({ > cols <- selected_columns() > req(cols) > data <- data() > data$dep <- cols$dependent > data$indep1 <- cols$independent1 > data$indep2 <- cols$independent2 > data$rand <- cols$random > lmer(dep ~ indep1 + indep2 + (1|rand), data = data) > }) > > # Instructional text > output$main_effects <- renderText({ > req(data()) > "Two-way ANOVA, main effects" > }) > > # Run two-way main effects model > output$model_summary_ME <- renderPrint({ > req(main_effects_model()) > Anova(main_effects_model(), type = c("III")) > }) > > > output$mod_diagnostic <- renderText({ > req(main_effects_model()) > "Below, the `DHARMa` package is used to check model assumptions. If > assumptions are not met, then data transformations may be needed before > proceeding." > }) > > output$diagnostic_plot <- renderPlot({ > req(interaction_model()) > plotQQunif(interaction_model()) > }) > > output$graph <- renderUI({ > req(data(), input$column2, input$column3) > selectInput("graph", "Which variable would you like to graph?", choices > = c(input$column2, input$column3, "interaction")) > }) > > output$model_selection <- renderUI({ > req(main_effects_model(), interaction_model()) > selectInput("model_selection", "Which ANOVA model do you want to > graph?", choices = c("Main effects model", "Interaction model")) > }) > > # Create a reactive expression to store the selected graph variable > selected_graph <- reactive({ > input$graph > }) > > # Create a reactive expression to store the selected model > selected_model <- reactive({ > input$model_selection > }) > > # Render the plot based on the selected variables > output$graph_plot <- renderPlot({ > req(data(), selected_graph(), selected_model()) > cols <- selected_columns() > > if (selected_graph() == cols$column2 | selected_model() == "Main > effects model") { > > # Mean separation: First column > mod_means_cotr1 <- emmeans(main_effects_model(), pairwise ~ > cols$column2, > adjust = 'tukey', > type = 'response') > > mod_means1 <- multcomp::cld(object = mod_means_cotr1$emmeans, > LETTERS = "letters") > > # Graph: First column > ggplot(mod_means1, aes_string(x = cols$column2, y = cols_column1))+ > geom_bar(stat="identity", width = 0.6, position = "dodge", col > "black", fill = "purple3")+ > geom_errorbar(aes(ymin = emmean, ymax = emmean + SE), width = 0.3, > position = position_dodge(0.6))+ > xlab(cols$column2)+ > ylab(cols$column1)+ > theme(plot.title=element_text(hjust=0.5, size = 20), > plot.subtitle = element_text(hjust = 0.5, size = 15), > axis.text = element_text(size = 17), > axis.title = element_text(size = 20))+ > geom_text(aes(label=.group, y=emmean + SE), vjust = -0.9, size = 8) > + > #ylim(0, 105)+ > scale_x_discrete(labels = function(x) str_wrap(x, width = 7)) > > > } > }) > > } > shinyApp(ui, server) > > [[alternative HTML version deleted]] > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide > http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >[[alternative HTML version deleted]]
Ivan Krylov
2024-Jun-06 15:05 UTC
[R] R Shiny Help - Trouble passing user input columns to emmeans after ANOVA analysis
? Wed, 5 Jun 2024 19:07:19 -0500 I B <ibarnhart055 at gmail.com> ?????:> However, I am getting the following error: *"Argument is of length > zero."*> if (selected_graph() == cols$column2 | selected_model() == "Main > effects model") {The error must be coming from here. At least one of selected_graph(), cols$column2, selected_model() is a zero-length object (maybe NULL) at this point, which makes the result of the whole expression zero-length too. if (...) only accepts logical scalars, hence the error. -- Best regards, Ivan