In the example code posted at the bottom, I get different results for the as.factor()
function when running the code inside a Shiny reactive versus running it outside of Shiny. What am I doing wrong? I think I missed something basic in my Shiny lessons.
Data is the lung
data from the "survival" package. Object lung_1
in my example code is generated outside of Shiny, and object lung_2
is generated inside Shiny as a reactive. Object lung_1
is correct, and object_2 is incorrect, as illustrated below. Both lung_1
and lung_2
should be the same. The below example assumes "sex" has been selected in the selectInput()
as the group variable, and it should be a factor class.
Code:
library(shiny)
library(survival)
lung_1 <- lung %>% mutate(group = as.factor(sex))
ui <- fluidPage(
selectInput(
"varCon",
"Grouping variable:",
c("None" = 1,
"sex" = "sex",
"ph.ecog" = "ph.ecog"
)
)
)
server <- function(input, output, session) {
lung_2 <- reactive({lung %>% mutate(group = as.factor(input$varCon))})
# throw reactive DF into global environment to peek at what's going on...
oe <- reactive({lung_2()})
observeEvent(oe(),{lung_2.R <<- oe()})
}
shinyApp(ui, server)
The issue you are facing is due to the difference in timing between the execution of the code outside and inside Shiny.
When you run the code outside Shiny, the as.factor() function is executed immediately after the mutate() function. This means that the resulting group column is of class factor.
However, when you run the code inside Shiny, the as.factor() function is executed only when the reactive expression is triggered. This means that the group column is of class character until the reactive expression is triggered and the as.factor() function is executed.
To fix this issue, you can convert the group column to a factor inside the reactive expression, rather than using mutate().
library(shiny)
library(survival)
lung_1 <- lung %>% mutate(group = as.factor(sex))
ui <- fluidPage(
selectInput(
"varCon",
"Grouping variable:",
c("None" = 1,
"sex" = "sex",
"ph.ecog" = "ph.ecog"
)
)
)
server <- function(input, output, session) {
lung_2 <- reactive({
data <- lung
if(input$varCon != 1) {
data$group <- data[[input$varCon]]
} else {
data$group <- NA_character_
}
data$group <- as.factor(data$group)
return(data)
})
# throw reactive DF into global environment to peek at what's going on...
oe <- reactive({lung_2()})
observeEvent(oe(),{lung_2.R <<- oe()})
}
shinyApp(ui, server)