Passing a reactive value to a plotting function as argument - r

I am trying to pass a reactive value derived from the selectizeInput select1 to a plotting function. The reactive value itself is dependent on input from awesomeRadio radio1.
Unfortunately, passing this value to the plot function does not work, although it's accessible by renderText(). Here is an example:
library(shiny)
library(shinydashboard)
##### plot function ------------------------
plot_function <- function(highlight){
plot(1:9)
points(x=c(1:9)[highlight],
y=c(1:9)[highlight],
col="red")
}
##### ui ------------------------
header <- dashboardHeader(
title = "Title",
titleWidth = 500
)
body <- dashboardBody(
fluidRow(
column(width = 4,
box(title = "Plot 1",
plotOutput("plot1", height = 300)
),
box(width = NULL, status = "warning",
awesomeRadio(inputId = "radio1",
label = "Radio1",
choices = c("Option1","Option2"),
inline = TRUE,
status="primary"
),br(),
uiOutput("select1"))
),
column(width = 3,
box(width = NULL, status = "warning",
textOutput(outputId = "option1")),
box(width = NULL, status = "warning",
textOutput(outputId = "option2")))
)
)
ui = dashboardPage(
header,
dashboardSidebar(disable = TRUE),
body
)
##### server ------------------------
server = function(input, output) {
onSessionEnded(stopApp)
choices = reactive({
if (input$radio1=="Option1") {
1:4
} else if (input$radio1=="Option2") {
5:8
}
})
output$select1 <- renderUI({
selectizeInput("select1", label="Select1",
choices=choices())
})
tmp = reactive({input$radio1})
tmp2 = reactive({input$select1})
output$plot1 <- renderPlot(plot_function(highlight = tmp2()))
output$option1 = renderText(paste(tmp()))
output$option2 = renderText(paste(tmp2()))
}
##### ui ------------------------
shinyApp(ui,server)
Also, I don't quite understand the different behavior of tmp and tmp2, since passing tmp to the plot function would work.
Thank you for any help!

After few changes in your code
library(shiny)
library(shinyWidgets)
ui <- fluidPage(
fluidRow(
column(width = 4,
box(title = "Plot 1",
plotOutput("plot1", height = 300)
),
box(width = NULL, status = "warning",
awesomeRadio(inputId = "radio1",
label = "Radio1",
choices = c("Option1","Option2"),
inline = TRUE,
status = "primary"
),br(),
uiOutput("select1"))
),
column(width = 3,
box(width = NULL, status = "warning",
textOutput(outputId = "option1")),
box(width = NULL, status = "warning",
textOutput(outputId = "option2")))
)
)
##### server ------------------------
server <- function(input, output) {
onSessionEnded(stopApp)
choices <- reactive({
if (input$radio1 == "Option1") {
1:4
} else if (input$radio1 == "Option2") {
5:8
}
})
output$select1 <- renderUI({
selectizeInput("sel", label = "Select1",
choices = choices())
})
output$plot1 <- renderPlot({
plot(1:9)
points(x = c(1:9)[as.numeric(input$sel)],
y = c(1:9)[as.numeric(input$sel)],
col = "red")
})
output$option1 <- renderText(input$radio1)
output$option2 <- renderText(input$sel)
}
shinyApp(ui,server)

Related

How to fetch the dynamic slider values in r shiny app?

I stuck in printing dynamic slider values. In the following code I tried to print the dynamic slider values but it's not possible.
library(shinydashboard)
library(DT)
ui <- dashboardPage(
dashboardHeader(title = "Dynamic slider"),
dashboardSidebar(
tags$head(
tags$style(HTML('.skin-blue .main-sidebar {
background-color: #666666;
}'))
),
sidebarMenu(
menuItem("Input data", tabName = 'input_data')
),
fileInput(
"file",
"Choose CSV File",
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")
),
checkboxInput("header",
"Header",
value = TRUE),
radioButtons(
"disp",
"Display",
choices = c(Head = "head",
All = "all"),
selected = "head"
),
sliderInput(
inputId = 'slr',
label = 'Slider range',
min = 0,
max = 3,
value = c(0.5,3),
step = 0.5
),
selectInput(
inputId = 'var',
label = 'Variables',
'Names',
multiple = TRUE
),
uiOutput('sliders')
),
dashboardBody(tabItems(
tabItem(tabName = 'input_data',
fluidRow(
box(width = 12,
dataTableOutput('table'),
title = 'Raw data'),
box(width = 6,
verbatimTextOutput('slider1'),
title = 'slider range'),
box(width = 6,
verbatimTextOutput('slider2'),
title = 'dynamic slider value')
)
)
))
)
server <- function(input, output) {
dataset <- reactive({
req(input$file)
read.csv(input$file$datapath,header = input$header)
})
observe(
output$table <- DT::renderDataTable({
if (input$disp == 'head') {
head(dataset())
}
else{
dataset()
}
})
)
observe({
updateSelectInput(inputId = 'var',choices = c(' ',names(dataset())))
})
variables <- reactive({
input$var
})
sli <- reactive({
lapply(1:length(variables()), function(i){
inputName <- variables()[i]
sliderInput(inputName, inputName,
min = 0, max = 1, value = c(0.3,0.7))
})
})
output$sliders <- renderUI({
do.call(tagList,sli())
})
output$slider1 <- renderPrint({
input$slr
})
output$slider2 <- renderPrint({
sli()
})
}
shinyApp(ui = ui, server = server)
Any suggestions will be appreciated, Is there any other method to get dynamic sliders based on selected variables or How can we get the values of the dynamic slider here??
There may be better ways to structure your app, but here is a solution that follows your general approach. There are 4 modifications to what you already have:
There is no need to define the reactive variables when you can just use input$var directly. The proposed solution eliminates this reactive.
Using req(input$var) will prevent components dependent on that selectInput from trying to render when a selection has not been made.
Since input$var defines the id of the dynamic slider, you can use this to retrieve the slider's values (i.e., input[[input$var]]).
Since you have specified "multiple = TRUE", a few nested paste statements are used to create a single string representing the values of all (potentially multiple) dynamic sliders.
The below app includes these modifications, and I believe, achieves what you are trying to accomplish.
library(shinydashboard)
library(DT)
ui <- dashboardPage(
dashboardHeader(title = "Dynamic slider"),
dashboardSidebar(
tags$head(
tags$style(HTML('.skin-blue .main-sidebar {
background-color: #666666;
}'))
),
sidebarMenu(
menuItem("Input data", tabName = 'input_data')
),
fileInput(
"file",
"Choose CSV File",
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")
),
checkboxInput("header",
"Header",
value = TRUE),
radioButtons(
"disp",
"Display",
choices = c(Head = "head",
All = "all"),
selected = "head"
),
sliderInput(
inputId = 'slr',
label = 'Slider range',
min = 0,
max = 3,
value = c(0.5,3),
step = 0.5
),
selectInput(
inputId = 'var',
label = 'Variables',
'Names',
multiple = TRUE
),
uiOutput('sliders')
),
dashboardBody(tabItems(
tabItem(tabName = 'input_data',
fluidRow(
box(width = 12,
dataTableOutput('table'),
title = 'Raw data'),
box(width = 6,
verbatimTextOutput('slider1'),
title = 'slider range'),
box(width = 6,
verbatimTextOutput('slider2'),
title = 'dynamic slider value')
)
)
))
)
server <- function(input, output) {
dataset <- reactive({
req(input$file)
read.csv(input$file$datapath,header = input$header)
})
observe(
output$table <- DT::renderDataTable({
if (input$disp == 'head') {
head(dataset())
}
else{
dataset()
}
})
)
observe({
updateSelectInput(inputId = 'var',choices = c(' ',names(dataset())))
})
sli <- reactive({
lapply(1:length(input$var), function(i){
inputName <- input$var[i]
sliderInput(inputName, inputName,
min = 0, max = 1, value = c(0.3,0.7))
})
})
output$sliders <- renderUI({
req(input$var)
do.call(tagList,sli())
})
output$slider1 <- renderPrint({
input$slr
})
output$slider2 <- renderPrint({
req(input$var)
paste(
sapply(
input$var,
function(x) {
paste(x, paste(input[[x]], collapse = ', '), sep = ': ')
}
),
collapse = '; '
)
})
}
shinyApp(ui = ui, server = server)

Dynamic left menu listing items downward instead of to the right

I am trying to create a dynamic left menu (header), but the items are listed downward instead of to the right. I guess it has to do with the tagList wrapper when defining the UI.
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(shinyWidgets)
library(stringr)
ui = dashboardPage(
dashboardHeader(
leftUi = tagList(uiOutput("filter"))
),
dashboardSidebar(
pickerInput(
"inputParameters",
"Parameters:",
choices = c("a", "b", "c"),
multiple = TRUE,
options = list(
`actions-box` = TRUE,
size = 10,
`selected-text-format` = "count > 1"
)
)
),
dashboardBody(),
title = "DashboardPage"
)
server = function(input, output) {
params <- reactive(input$inputParameters)
output$filter = renderUI(
lapply(seq_along(params()), function(i) {
dropdownButton(
inputId = paste0("mydropdown", i),
label = params()[i],
icon = icon("sliders"),
status = "primary",
circle = FALSE,
selectizeInput(
paste0("input", paste0(str_to_title(params()[i]))),
paste0(paste0(str_to_title(params()[i]), ":")),
choices = 1:3,
multiple = TRUE,
selected = 1:3
)
)
})
)
}
shinyApp(ui, server)
Not tested, I would try:
output$filter = renderUI({
ddbuttons <- lapply(seq_along(params()), function(i) {
dropdownButton(
inputId = paste0("mydropdown", i),
label = params()[i],
icon = icon("sliders"),
status = "primary",
circle = FALSE,
selectizeInput(
paste0("input", paste0(str_to_title(params()[i]))),
paste0(paste0(str_to_title(params()[i]), ":")),
choices = 1:3,
multiple = TRUE,
selected = 1:3
)
)
})
do.call(splitLayout, ddbuttons)
})
And don't use tagList, just uiOutput("filter").

Reactively updating sidebar in modular Shiny app

I have a modularized Golem app using bs4Dash. I want to update the active sidebar tab from an actionBttn that is dynamically generated from renderUI. While updatebs4ControlbarMenu works as expected as shown here, it does not work in the modularized version of the application. What am I doing wrong? I suspect it is related to input[[btnID]] management across modules but I struggle to find the solution.
Working example without modules as shown here:
library(shiny)
library(shinyWidgets)
library(bs4Dash)
library(tidyverse)
shinyApp(
ui = bs4DashPage(
sidebar_collapsed = FALSE,
controlbar_collapsed = TRUE,
enable_preloader = FALSE,
navbar = bs4DashNavbar(skin = "dark"),
sidebar = bs4DashSidebar(
inputId = "sidebarState",
bs4SidebarMenu(
id = "sidebr",
bs4SidebarMenuItem(
"Tab 1",
tabName = "tab1"
),
bs4SidebarMenuItem(
"Tab 2",
tabName = "tab2"
)
)
),
bs4DashBody(
bs4TabItems(
bs4TabItem(
tabName = "tab1",
h1("Welcome!"),
fluidRow(
pickerInput(
inputId = "car",
label = "Car",
choices = row.names(mtcars),
selected = head(row.names(mtcars), 3),
multiple = TRUE,
options = list(
`actions-box` = TRUE)
),
pickerInput(
inputId = "gear",
label = "Gear",
choices = unique(mtcars$gear),
selected = unique(mtcars$gear),
multiple = TRUE,
options = list(
`actions-box` = TRUE)
)
),
fluidRow(
column(6,
uiOutput("uiboxes")
)
)
),
bs4TabItem(
tabName = "tab2",
h4("Yuhuuu! You've been directed automatically in Tab 2!")
)
)
)
),
server = function(input, output, session) {
submtcars <- reactive({
req(input$car, input$gear)
mtcars %>%
mutate(
carnames = rownames(mtcars)) %>%
filter(
carnames %in% input$car &
gear %in% input$gear
)
})
observeEvent( submtcars(), {
n_ex <- nrow(submtcars())
output$uiboxes <- renderUI({
lapply(1:n_ex, FUN = function(j) {
print(paste("j is ", j))
bs4Box(
title = submtcars()$carnames[j],
width = 12,
str_c("Number of gears:", submtcars()$gear[j]),
btnID <- paste0("btnID", j),
print(btnID),
fluidRow(
column(
2,
actionBttn(
inputId = btnID,
icon("search-plus")
)
)
)
)
})
})
lapply(1:n_ex, function(j) {
btnID <- paste0("btnID", j)
observeEvent(input[[btnID]] , {
updatebs4ControlbarMenu(
session,
inputId = "sidebr",
selected = "tab2"
)
})
})
})
}
)
Modularized attempt not working:
library(shiny)
library(shinyWidgets)
library(bs4Dash)
library(tidyverse)
mod_exlib_ui <- function(id){
ns <- NS(id)
tagList(
fluidRow(
pickerInput(
inputId = ns("car"),
label = "Car",
choices = row.names(mtcars),
selected = head(row.names(mtcars), 3),
multiple = TRUE,
options = list(
`actions-box` = TRUE)
),
pickerInput(
inputId = ns("gear"),
label = "Gear",
choices = unique(mtcars$gear),
selected = unique(mtcars$gear),
multiple = TRUE,
options = list(
`actions-box` = TRUE)
)
),
fluidRow(
column(6,
uiOutput(ns("uiboxes"))
)
)
)
}
mod_exlib_server <- function(id){
moduleServer( id, function(input, output, session){
ns <- session$ns
submtcars <- reactive({
# req(input$car, input$gear)
mtcars %>%
dplyr::mutate(
carnames = rownames(mtcars)) %>%
dplyr::filter(
carnames %in% input$car &
gear %in% input$gear
)
})
observeEvent( submtcars(), {
n_ex <- nrow(submtcars())
output$uiboxes <- renderUI({
lapply(1:n_ex, FUN = function(j) {
print(paste("j is ", j))
bs4Box(
title = submtcars()$carnames[j],
width = 12,
paste("Number of gears: ", submtcars()$gear[j]),
btnID <- paste0("btnID", j),
print(btnID),
fluidRow(
column(
2,
actionBttn(
inputId = ns(btnID),
icon("search-plus")
)
)
)
)
})
})
lapply(1:n_ex, function(j) {
btnID <- paste0("btnID", j)
observeEvent(input[[btnID]] , {
print(btnID)
updatebs4ControlbarMenu(
session,
inputId = "sidebr",
selected = "exdet2"
)
})
})
})
})
}
app_ui <- tagList(
bs4DashPage(
navbar = bs4DashNavbar(),
sidebar = bs4DashSidebar(
expand_on_hover = TRUE,
inputId = "sidebarState",
bs4SidebarMenu(
id = "sidebr",
bs4SidebarMenuItem(
"Tab 1",
tabName = "tab1"
),
bs4SidebarMenuItem(
"Tab 2",
tabName = "tab2"
)
)
),
bs4DashBody(
bs4TabItems(
bs4TabItem(
tabName = "tab1",
h1("Welcome!"),
mod_exlib_ui("exlib_ui_1")
),
bs4TabItem(
tabName = "tab2",
h4("Yuhuuu! You've been directed automatically in Tab 2!")
)
)
)
)
)
app_server <- function( input, output, session ) {
# Your application server logic
mod_exlib_server("exlib_ui_1")
}
shinyApp(
ui = app_ui,
server = app_server)
After exploring the example of function updatebs4TabSetPanel() that is in the same family, it seems that the selected value needs to be a number.
Hence, you can use this code with CRAN version 0.5.0:
updatebs4ControlbarMenu(
session,
inputId = "sidebr",
selected = "2" #"exdet2"
)

Print str() of table in shiny dashboard

I am a newbie to shiny dashboard. I want to know how to print str() of the table which i have imported in shiny dashboard. my code is not working. When i print str(), i get the below output,
str()
Please check the code which i have written,
library(shiny)
library(shinydashboard)
library(DT)
ui <- dashboardPage(
dashboardHeader(title = "Analytics Workbench 2.0", titleWidth = 250,
dropdownMenuOutput("msgs")),
dashboardSidebar(
sidebarMenu(
fileInput("Table1", "Train Data"),
fileInput("Table2", "Test Data"),
menuItem("Variable Analysis", icon = icon("edit"),
menuSubItem("Uni-Variate Analysis"),
menuSubItem("Multi-Variate Analysis"))
)
),
dashboardBody(
fluidRow(
column(12, box(title = "Train Data", width = 6, solidHeader = TRUE, status = "warning",
collapsible = TRUE, DT::DTOutput("Train")),
box(title = "Test Data", width = 6, solidHeader = TRUE, status = "warning",
collapsible = TRUE, DT::DTOutput("Test")))),
fluidRow(
column(12, box(title = "Structure", width = 6, solidHeader = TRUE, status = "warning",
collapsible = TRUE, verbatimTextOutput("str1")),
box(title = "Structure", width = 6, solidHeader = TRUE, status = "warning",
collapsible = TRUE, verbatimTextOutput("str2"))))
)
)
server <- function(input, output) {
output$msgs <- renderMenu({
msg <- apply(read.csv("messages.csv"), 1, function(row){
messageItem(from = row[["from"]], message = row[["message"]]) })
dropdownMenu(type = "messages", .list = msg)
})
output$Train <- DT::renderDT({
if (is.null(input$Table1)) return(NULL)
data1 <- read.table(input$Table1$datapath, fill = TRUE, header=T, sep=",")
DT::datatable(data1, options = list(scrollX = TRUE))
})
output$Test <- DT::renderDT({
if (is.null(input$Table2)) return(NULL)
data2 <- read.table(input$Table2$datapath, fill = TRUE, header=T, sep=",")
DT::datatable(data2, options = list(scrollX = TRUE))
})
output$str1 <- renderText({
paste(capture.output(str(input$Table1)), collapse = "\n")
})
output$str2 <- renderText({
paste(capture.output(str(input$Table1)), collapse = "\n")
})
}
I am not able to find out the input to be given for str()
Thanks
Balaji
Switch out your textOutput for verbatimTextOutput. Also, you require a reactive to treat the fileInput... specifically take note that you should trap the case when the input value is NULL.
app.R
library(shiny)
write.csv(mtcars, "mtcars.csv") # file created to test file input
ui <- fluidPage(
mainPanel(
verbatimTextOutput("strfile"),
fileInput("file1", "File")
)
)
server <- function(input, output) {
df <- reactive({
if (is.null(input$file1)) {
return(NULL)
} else {
read.csv(input$file1$datapath, row.names = 1) # note the row.names are dependent on your input requirements
}
})
output$strfile <- renderPrint({str(df())})
}
shinyApp(ui = ui, server = server)
To get this output...

Dynamically passing selectInput values from UI to Server code in R

The process_map() function in the server in the R shiny script creates the diagram image as below. My requirement is that there are two attributes "FUN" and "units" that are part of the performance() function. They have standard four values each that are available in the ui code below under PickerInput ID's Case4 and Case5. Currently, I am hard coding the value to create the map, can you help me to use the id's in the server code and make it dynamic such that when I select the value in the PickerInput, the formula fetches the value directly. Thanks and please help.
library(shiny)
library(shinydashboard)
library(bupaR)
library(processmapR)
library(lubridate)
library(dplyr)
library(edeaR)
library(shinyWidgets)
library(DiagrammeR)
ui <- dashboardPage(
dashboardHeader(title = "Diagram Plot",titleWidth = 290),
dashboardSidebar(width = 0),
dashboardBody(
tabsetPanel(type = "tab",
tabPanel("Overview", value = 1,
box(
column(1,
dropdown(
pickerInput(inputId = "resources",
label = "",
choices = c("Throughput Time"),
choicesOpt = list(icon = c("fa fa-bars",
"fa fa-bars",
"fa fa-safari")),
options = list(`icon-base` = "")),
circle = FALSE, status = "primary", icon = icon("list", lib = "glyphicon"), width = "300px"
),
conditionalPanel(
condition = "input.resources == 'Throughput Time' ",
tags$br(),
tags$br(),
tags$br(),
dropdown(
pickerInput(inputId = "Case4",
label = "Select the Process Time Summary Unit",
choices = c("min","max","mean","median"), options = list(`actions-box` = TRUE),
multiple = F),
circle = FALSE, status = "primary", icon = icon("eye-close", lib = "glyphicon"), width = "300px"
),
tags$br(),
tags$br(),
tags$br(),
dropdown(
pickerInput(inputId = "Case5",
label = "Select the Process Time Unit",
choices = c("mins","hours","days","weeks"), options = list(`actions-box` = TRUE),
multiple = F, selected = "days"),
circle = FALSE, status = "primary", icon = icon("eye-close", lib = "glyphicon"), width = "300px"
))),
title = "Process Map",
status = "primary",height = "575", width = "500",
solidHeader = T,
column(10,grVizOutput("State")),
align = "left")
),
id= "tabselected"
)))
server <- function(input, output) {
output$State <- renderDiagrammeR(
{
if(input$resources == "Throughput Time")
patients %>% process_map(performance(FUN = mean,units = "days"))
else
return()
})}
shinyApp(ui, server)
test this:
output$State <- renderDiagrammeR({
if(input$resources == "Throughput Time")
{
if(input$Case4=="mean"){
patients %>% process_map(performance(FUN = mean,units = input$Case5))}
else if(input$case4=="min"){
patients %>% process_map(performance(FUN = min,units = input$Case5))
}else if(input$case4=="max"){
patients %>% process_map(performance(FUN = max ,units = input$Case5))
}else{
patients %>% process_map(performance(FUN = median ,units = input$Case5))
}
}else
return()
})
or you can use this:
patients %>%
process_map(performance(FUN = eval(parse(text=input$Case4)) ,units = input$Case5))
enjoy;)
here is a sample:
library(shiny)
ui <- fluidPage(
selectInput(inputId = "func", label = "Choose The Function", choices = c("mean", "sum", "median"))
,
textOutput("text")
)
server <- function(input, output, session) {
main_data <- reactive({
data.frame(a= rnorm(100), b=rnorm(100) )
})
output$text <- renderText({
df <- main_data()
apply(df,2, FUN = eval(parse(text=input$func)) )
})
}
shinyApp(ui = ui, server = server)
You could use do.call to call a function from its name, see the example below. You can add arguments by adding them in the list in the do.call function, e.g. list(x,units=input$Case5).
library(shiny)
x=c(1,2,3,4,5,6,7)
ui <- fluidPage(
selectInput('select','Select Function: ', choices=c('mean','max','min','median')),
textOutput('text')
)
server <- function(input,output)
{
output$text <- renderText({
result = do.call(input$select, list(x))
paste0('The ', input$select, ' of [', paste(x,collapse=', '),'] is ', result)
})
}
shinyApp(ui,server)
Hope this helps!

Resources