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