Reputation: 135
I've created the Shiny app below:
library(shiny)
library(shinyWidgets)
library(tidyverse)
tbl1 <- tibble(obs = as_factor(letters[1:3]), val = -1:1)
tbl2 <- tibble(obs = as_factor(letters[1:3]), val = 0:2)
flag_outliers <- function(tbl) {
tbl %>% mutate(is_outlier = near(val, min(val)) | near(val, max(val)))
}
ui <- fluidPage(
column(6,
radioButtons("tbl", "Select tibble", choices = c("tbl1", "tbl2")),
actionButton("flag_w_func", "Flag outliers with function"),
pickerInput(
"user_choices", "Flag outliers yourself",
letters[1:3], multiple = TRUE, options = pickerOptions(actionsBox = TRUE)
)
),
column(6, tableOutput("tbl_w_flags"))
)
server <- function(input, output, session) {
tbl <- reactive(switch(input$tbl, tbl1 = tbl1, tbl2 = tbl2))
tbl_w_flags <- reactive(flag_outliers(tbl())) # Not sure what this should be
output$tbl_w_flags <- renderTable(tbl_w_flags())
}
shinyApp(ui, server)
This defines two tibbles, tbl1
and tbl2
, and allows the user to choose one; their choice is stored in tbl
in the server function. I want to create another tibble in the server function called tbl_w_flags
that's tbl
plus an is_outlier
column.
If the user clicks on the "Flag outliers with function" button, the is_outlier
column should be set using flag_outliers()
. Also, the dropdown list user_choices
should display check marks next to the observations that have been flagged by flag_outliers()
and those observations only.
If the user checks or unchecks observations in the dropdown list, the is_outlier
column should be updated appropriately - the appropriate values should be changed to TRUE
or FALSE
.
Thus, tbl_w_flags
needs to be modified if the button is clicked or choices are made in the dropdown list, and the dropdown list needs to be modified if the button is clicked.
I don't have much Shiny experience and am struggling to figure out how to do this. Is this possible? If so, how can it be accomplished?
Upvotes: 2
Views: 53
Reputation: 1302
I removed tbl_w_flags
and directly updated tbl()
, two reactive are not necessary here. I also used reactiveVal
for reactive
and added an updatePickerInput
to also update the picker if the button is clicked
library(shiny)
library(shinyWidgets)
library(tidyverse)
tbl1 <- tibble(obs = as_factor(letters[1:3]), val = -1:1)
tbl2 <- tibble(obs = as_factor(letters[1:3]), val = 0:2)
flag_outliers <- function(tbl) {
tbl %>% mutate(is_outlier = near(val, min(val)) | near(val, max(val)))
}
ui <- fluidPage(
column(6,
radioButtons("tbl", "Select tibble", choices = c("tbl1", "tbl2")),
actionButton("flag_w_func", "Flag outliers with function"),
pickerInput(
"user_choices", "Flag outliers yourself",
letters[1:3], multiple = TRUE, options = pickerOptions(actionsBox = TRUE)
)
),
column(6, tableOutput("tbl_w_flags"))
)
server <- function(input, output, session) {
tbl <- reactiveVal()
observe(tbl(switch(input$tbl, tbl1 = tbl1, tbl2 = tbl2)))
observe(input$user_choices)
observeEvent(input$flag_w_func, {
old_tbl <- tbl()
new_tbl <- flag_outliers(old_tbl)
# Update reactive tbl and user_choice pickerInput
tbl(new_tbl)
new_choices <- new_tbl %>% filter(is_outlier) %>% pull(obs)
updatePickerInput(session, "user_choices", selected = new_choices)
})
observeEvent(input$user_choices, {
old_tbl <- tbl()
new_tbl <- old_tbl %>% mutate(is_outlier = c(obs %in% input$user_choices))
# Update reactive tbl()
tbl(new_tbl)
})
output$tbl_w_flags <- renderTable(tbl())
}
shinyApp(ui, server)
Edit:
If you like to reset the picker whenever the tibble is changed (using the radio buttons), change your first observer to
observe({
tbl(switch(input$tbl, tbl1 = tbl1, tbl2 = tbl2))
updatePickerInput(session, "user_choices", selected = character(0))
})
Upvotes: 1