I want to be able to design a set of UI that can call R's built-in functions, but the current problem lies in the data selection when calling the function. I need to return the calculation result of a function to my UI interface so that another function can be arbitrary Select the variables in the current environment as the input of the function. This is my current code. Can anyone give me some suggestions or some cases?
library(shiny)
function_choose = c("sin","cos")
ui <- fluidPage(
selectInput('f', 'function_choose', function_choose,
selected = function_choose[[1]]),
sidebarPanel(
conditionalPanel(condition = "input.f=='sin'",
mainPanel(
selectInput('sin_dat','data',c("I want to show all the variables in the workspace here ")),
actionButton(inputId = "sin_run",label = "RUN")
)
),
conditionalPanel(condition = "input.f=='cos'",
mainPanel(
selectInput('workspace','data',c("I want to show all the variables in the workspace here "))),
actionButton(inputId = "cos_run",label = "RUN")
)
),
mainPanel(
textOutput("text")
)
)
server <- function(input, output,session) {
data <- c(0.1,0.2,0.3)
observeEvent(input$sin_run,{
data_sined <- sin(data)
output$text <- renderText({
"data_sined is created"
})
})
observeEvent(input$cos_run,{
data_cosed<- cos(data)
output$text <- renderText({
"data_cosed is created"
})
})
}
shinyApp(ui = ui, server = server)
I changed the logic of your app to make it less complicated, I hope this is still ok for your purpose. We can use ls() to get a character vector of all variables in the global (or any other) environment. If we define a vector function_choose in the global environment, then this will be available too. We could easily circumvent this by defining the choices argument inside selectInput or by specifying a names pattern that is selected by ls(). Once we have selected a variable, the input$data returns a character vector. To access the underyling data based on a character vector we use get().
library(shiny)
function_choose = c("sin","cos")
shinyApp(
ui = fluidPage(
sidebarPanel(
selectInput('f', 'function_choose', choices = function_choose,
selected = function_choose[1]),
selectInput('data','data', choices = ls()),
actionButton(inputId = "run",label = "RUN")
),
mainPanel(
textOutput("text")
)
),
server = function(input, output,session) {
res <- eventReactive(input$run, {
dat <- get(input$data)
switch(input$f,
sin = sin(dat),
cos = cos(dat)
)
})
output$text <- renderText({
res()
})
})
Related
I have the following app which allows for text to be entered and it is then saved as VALUE and printed on a panel.
Although it looks like I can only do this with one text input at a time - even if I click add (so I don't believe this button is working). On top of that I would like for the user to be able to add multiple inputs (like I have below).
And then my VALUE function should be list with multiple inputs.
code below
library(shiny)
ui <- fluidPage(
headerPanel("R Package App"),
sidebarPanel(
# selectInput("options", "options", choices=c('abc','def')),
textInput("textbox", "Enter R Package Name", ""),
actionButton("add","Add")
),
mainPanel(
textOutput("caption")
)
)
server <- function(input, output, session) {
observe({
VALUE <- ''
if(input$add>0) {
isolate({
VALUE <- input$textbox
})
}
updateTextInput(session, inputId = "textbox", value = VALUE)
})
output$caption <- renderText({
input$textbox
})
}
shinyApp(ui = ui, server = server)
Have you considered using selectizeInput with it's create option?
library(shiny)
packagesDF <- as.data.frame(installed.packages())
ui <- fluidPage(
headerPanel("R Package App"),
sidebarPanel(
selectizeInput(
inputId = "selectedPackages",
label = "Enter R Package Name",
choices = packagesDF$Package,
selected = NULL,
multiple = TRUE,
width = "100%",
options = list(
'plugins' = list('remove_button'),
'create' = TRUE,
'persist' = TRUE
)
)
),
mainPanel(textOutput("caption"))
)
server <- function(input, output, session) {
output$caption <- renderText({
paste0(input$selectedPackages, collapse = ", ")
})
}
shinyApp(ui = ui, server = server)
I am attempting to custom build a user-interface regression tool in R shiny for practice (i.e. my own version of spss for my general use-cases). I'm having trouble with the critical step of generating a regression formula from the user-uploaded dataset. I want the user to be able to select a dependent variable from a dropdown menu (and eventually to turn those generated variables into a formula in my server code).
I have tried to use a textOutput(names(userdata())) within the choices argument for a selectInput() function so that the user can select which of their variables should be a dependent variable once they have uploaded their dataset. However, this generates a list of properties of the dataset rather than the names of the columns themselves.
I've looked into other uses of reactive datasets that others have done but no one seems to have done precisely what I am trying to do or I am searching for them badly. (It seems like the most common probable use-case for Shiny, so I can't imagine how no one has figured this out yet, but I can't find anything)
library(shiny)
library(wired)
ui <- fluidPage(
sidebarLayout(sidebarPanel(
fileInput("FileInput", "Input Your Data Set (Must be .csv)"),
wired_select(inputId = "responsevar",
label = "Dependent Varibale:",
choices = textOutput(outputId = "variable_names")
)
), #sidebar panel
mainPanel(
tabsetPanel(
tabPanel("Table",
DT::dataTableOutput("table")
)
) #tabset Panel
) #main panel
) #sidebarlayout
) #fluidpage
server <- function(input, output, session) {
datasetInput <- reactive({
infile <- input$FileInput
if (is.null(infile))
return(NULL)
read.csv(infile$datapath, header = TRUE)
})
output$table = DT::renderDataTable(datasetInput())
output$variable_names <- reactive({
if (is.null(datasetInput()))
return(NULL)
names(datasetInput())
})
} #server
shinyApp(ui = ui, server = server)
textOutput is used to output text to the Shiny UI. This is includes generating appropriate HTML. As wired_select(..., choices = ???) is expecting an R object rather than HTML code this is unlikely to work.
One approach that is likely to work is using updateSelectInput. I do not know whether this has an equivalent function with the wired library, but in base shiny I would:
Initialise the selectInput with no choices
Update the choices in the drop down once the data has been selected
Try the following:
library(shiny)
ui <- fluidPage(
sidebarLayout(sidebarPanel(
fileInput("FileInput", "Input Your Data Set (Must be .csv)"),
selectInput(inputId = "responsevar",
label = "Dependent Varibale:",
choices = NULL)
), #sidebar panel
mainPanel(
tabsetPanel(
tabPanel("Table",
DT::dataTableOutput("table")
)
) #tabset Panel
) #main panel
) #sidebarlayout
) #fluidpage
server <- function(input, output, session) {
datasetInput <- reactive({
infile <- input$FileInput
if (is.null(infile))
return(NULL)
read.csv(infile$datapath, header = TRUE)
})
output$table = DT::renderDataTable(datasetInput())
observeEvent(datasetInput(),{
updateSelectInput(session, "responsevar", choices = names(datasetInput()))
})
} #server
shinyApp(ui = ui, server = server)
Hmm... as the above does not work with the wired library, I'll suggest another possible approach. (I can't install wired in my environment, so apologies if this is no better).
The idea here is to make the selector part of a dynamic R object (a UI object). Then if a file gets loaded, the UI object, which depends on the file, will also update.
library(shiny)
library(wired)
ui <- fluidPage(
sidebarLayout(sidebarPanel(
fileInput("FileInput", "Input Your Data Set (Must be .csv)"),
uiOutput("selector")
), #sidebar panel
mainPanel(
tabsetPanel(
tabPanel("Table",
DT::dataTableOutput("table")
)
) #tabset Panel
) #main panel
) #sidebarlayout
) #fluidpage
server <- function(input, output, session) {
datasetInput <- reactive({
infile <- input$FileInput
if (is.null(infile))
return(NULL)
read.csv(infile$datapath, header = TRUE)
})
output$table = DT::renderDataTable(datasetInput())
output$selector <- renderUI({
choices <- NULL
if(!is.null(datasetInput()))
choices <- names(datasetInput())
wired_select(inputId = "responsevar",
label = "Dependent Varibale:",
choices = choices)
})
} #server
Key differences to my original answer, are uiOutput replacing selectInput and a renderUI output component instead of an observer.
As an extension of this example:
https://shiny.rstudio.com/gallery/creating-a-ui-from-a-loop.html
Say you would like the for loop to be of a length determined by a numeric input. So for example, extending the linked example (using just the second part of it):
ui <- fluidPage(
title = 'Creating a UI from a dynamic loop length',
sidebarLayout(
sidebarPanel(
# Determine Length of Loop
numericInput(inputId = "NumLoop", "Number of Loops", value = 5, min = 1, max = 5, step = 1)
),
mainPanel(
# UI output
lapply(1:input.NumLoop, function(i) {
uiOutput(paste0('b', i))
})
)
)
)
server <- function(input, output, session) {
reactive({
lapply(1:input$NumLoop, function(i) {
output[[paste0('b', i)]] <- renderUI({
strong(paste0('Hi, this is output B#', i))
})
})
})
}
shinyApp(ui = ui, server = server)
As far as I can tell there are two problems with the code:
In the UI, I don't know how to legitimately use the input from NumLoop in the for loop of the UI output. I have experimented with the conditionalPanel function with no luck.
In the server, once I put the loop behind a reactive function to make use of input$NumLoop I no longer have access to those renderUI outputs in the UI.
Any ideas of how to solves these issues would be much appreciated.
This should do the trick, as per #Dean, yes the second renderUI shouldn't be there
library(shiny)
ui <- fluidPage(
title = 'Creating a UI from a dynamic loop length',
sidebarLayout(
sidebarPanel(
# Determine Length of Loop
numericInput(inputId = "NumLoop", "Number of Loops", value = 5, min = 1, max = 10, step = 1)
),
mainPanel(
# UI output
uiOutput('moreControls')
)
)
)
server <- function(input, output, session) {
output$moreControls <- renderUI({
lapply(1:input$NumLoop, function(i) {
strong(paste0('Hi, this is output B#', i),br())
})
})
}
shinyApp(ui = ui, server = server)
How can I pass additional arguments to a reactive context in Shiny? The purpose is to handover the arguments to the reactive context ("callback") when it is evaluated.
Think of the following Shiny server code. How can I make output$some print "some", output$different print "different" and so on?
for(i in c("some","different","values"){
output[[i]] <- renderText({
# i gets evaluated at some later point in time,
# and thus will always print "values"
i
})
}
The example below is intended to make the two render contexts reactive to the corresponding reactive value text1 and text2, but of course it only makes both depend on text2.
library(shiny)
ui <- fluidPage(
titlePanel("Test"),
sidebarLayout(
sidebarPanel(
),
mainPanel(
htmlOutput("text1"),
textOutput("text2"),
actionButton("test_btn1",label="test1"),
actionButton("test_btn2",label="test2")
)
)
)
server <- function(input, output) {
rv <- reactiveValues(
"text1"=NULL,
"text2"=NULL
)
bindings <- list(
list("var"="text1",
"function"=renderUI),
list("var"="text2",
"function"=renderText)
)
for(i in bindings){
output[[i[["var"]]]] <- i[["function"]]({
# i is always the second element unfortunately
rv[[i[["var"]]]]
})
}
observeEvent(input$test_btn1,{
rv$text1 <- tags$p("new value 1")
})
observeEvent(input$test_btn2,{
rv$text2 <- "new value 2"
})
}
shinyApp(ui = ui, server = server)
Try Map() instead of the for loop so the function gets called through each iteration:
library(shiny)
ui <- fluidPage(
titlePanel("Test"),
sidebarLayout(
sidebarPanel(
),
mainPanel(
htmlOutput("text1"),
textOutput("text2"),
actionButton("test_btn1",label="test1"),
actionButton("test_btn2",label="test2")
)
)
)
server <- function(input, output) {
rv <- reactiveValues(
"text1"=NULL,
"text2"=NULL
)
bindings <- list(
list("var"="text1",
"function"=renderUI),
list("var"="text2",
"function"=renderText)
)
Map(function(i){
output[[bindings[[i]][["var"]]]] <- bindings[[i]][["function"]]({
# i is always the second element unfortunately
rv[[bindings[[i]][["var"]]]]
})
}, 1:2)
observeEvent(input$test_btn1,{
rv$text1 <- "new value 1"
})
observeEvent(input$test_btn2,{
rv$text2 <- "new value 2"
})
}
shinyApp(ui = ui, server = server)
I am pretty new to Shiny and dealing with the following problem, upon pressing an actionButton in shiny, I want it to do multiple calculations. I use the handler of observeEvent.
An example:
library(shiny)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(`
actionButton("calc","calculate stuff")),
mainPanel(
textOutput("result")
)
)
)
server <- function(input,output){
observeEvent(input$calc, {output$result <- renderText({"only this is not enough"}) })
}
shinyApp(ui,server')`
Now what I would want is where the output$result is made in the server-observeEvent, I would like to perform additional tasks, say assign a variable a <- 12, calculate B4 <- input$ID1*inputID2 etc.
This can not be hard I imagine.. but I am just not getting there.
kind regards,
Pieter
You can use isolate, see this example:
library(shiny)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
numericInput(inputId = 'x', label = 'Select a value for x', value = 1),
actionButton( "calc", "calculate stuff" )
),
mainPanel(
textOutput("result")
)
)
)
server <- function(input, output) {
output$result <- renderText({
input$calc
isolate({
y<- input$x *2
paste("The result is:", y)
})
})
}
shinyApp(ui, server)