Shiny - conditionalPanel - set condition as output from server - r

I am trying to build an app in shiny that will be able to load a dataset in the server function and then based on the user choose and then if there is a factor variable to open check box using conditionalPanel. is there a way to output variable from the server as the condition of the condtionalPanel?
Here is what I tried:
library(shiny)
library(caret)
ui <- fluidPage(
selectInput('dataset', 'Select Dataset',
list(GermanCredit = "GermanCredit",
cars = "cars")),
conditionalPanel(
condition = "output.factorflag == true",
checkboxInput("UseFactor", "Add Factor Variable")
)
)
server <- function(input, output) {
# Loading the dataset
df <- reactive({
if(input$dataset == "GermanCredit"){
data("GermanCredit")
df <- GermanCredit
}else if(input$dataset == "cars"){
data(cars)
df <- cars
}
return(df)
})
# Loading the variables list
col_type <- reactive({
col_type <- rep(NA,ncol(df()))
for(i in 1:ncol(df())){
col_type[i] <- class(df()[,i])
}
return(col_type)
})
outputOptions(output, "factorflag", suspendWhenHidden = FALSE)
output$factorflag <- reactive({
if("factor" %in% col_type()){
factor.flag <- TRUE
} else {factor.flag <- FALSE}
}
)
}
shinyApp(ui = ui, server = server)
Thank you in advance!

You were almost there, you need to put the outputOptions after the declaration of factorflag. Just reengineered a bit your code:
library(shiny)
library(caret)
ui <- fluidPage(
selectInput('dataset', 'Select Dataset',
list(GermanCredit = "GermanCredit",
cars = "cars")),
conditionalPanel(
condition = "output.factorflag == true",
checkboxInput("UseFactor", "Add Factor Variable")
)
)
server <- function(input, output) {
# Loading the dataset
df <- reactive({
if(input$dataset == "GermanCredit"){
data("GermanCredit")
GermanCredit
}else {
data("cars")
cars
}
})
output$factorflag <- reactive("factor" %in% sapply(df(),class))
outputOptions(output, "factorflag", suspendWhenHidden = FALSE)
}
shinyApp(ui = ui, server = server)

Related

How to update select input inside renderIU?

I show you my shiny application, but I have a problem, I cannot update the selectimput, I have used updateSelectInput but it does not work.
I have two selectInputs inside a tabsetPanel, since I need to update the table with two filters, one is the category and the other the subcategory.
here my code.
library(shiny)
library(tidyverse)
library(DT)
cat1<-rep("LINEA BLANCA", 75)
cat2<- rep("VIDEO", 75)
subcat1<-rep("LAVADORAS", 40)
subcat2<- rep("REFRIS", 35)
subcat3<- rep("TV", 40)
subcat4<- rep("SONIDO", 35)
vent<-sample(100:900, 150, replace=T)
segm1<-rep("AAA", 25)
segm2<-rep("BBB", 25)
segm3<-rep("CCC", 25)
segm4<-rep("ABB", 25)
segm5<-rep("ACC", 25)
segm6<-rep("BAC", 25)
db<- tibble(segment=c(segm1,segm2,segm3,segm4,segm5,
segm1),CATEGORIA=c(cat1,cat2), SUBCAT=c(subcat1,subcat2, subcat3, subcat4), vent=vent)
ui <- fluidPage(
# App title
titlePanel("EXAMPLE"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
),
# Main panel for displaying outputs ----
mainPanel(
# Output: Tabset w/ plot, summary, and table ----
tabsetPanel(type = "tabs",
tabPanel("Ana_inv", uiOutput("selectcat"), uiOutput("selectsubcat"),DT::dataTableOutput("ana_inv")),
#tabPanel("Summary", verbatimTextOutput("summary")),
tabPanel("Table", tableOutput("table"))
)
)
)
)
server <- function(input, output, session) {
output$selectcat <- renderUI({
selectInput("Cat", "Seleccione Categoria", choices = c("ALL",as.vector(db$CATEGORIA)))
})
output$selectsubcat <- renderUI({
#opciones<- db_prueba %>% filter(CATEGORIA==input$CAT)
selectInput("Subcat", "Seleccione Subcategoria", choices = c("ALL",as.vector(db$SUBCAT)))
})
activar<- reactive({
req(input$Cat)
req(input$Subcat)
opciones<- db %>% filter(CATEGORIA==input$Cat)
if(input$Cat == "TODOS") {
filt1 <- quote(CATEGORIA != "#?><")
} else {
filt1 <- quote(CATEGORIA == input$Cat)
}
if (input$Subcat == "TODOS") {
filt2 <- quote(SUBCAT != "#?><")
} else {
filt2 <- quote(SUBCAT == input$Subcat)
}
db %>%
filter_(filt1) %>%
filter_(filt2) %>% group_by(segment)%>%
summarise(SKUs=n(),
vta=sum(vent))
})
# Return the formula text for printing as a caption ----
output$ana_inv <- DT::renderDataTable({
activar()
})
}
shinyApp(ui = ui, server = server)
So I need that if the category "LINEA BLANCA" is selected in the subcategory it only shows "REFRIS" and "LAVADORAS", but also if someone selects "ALL" in the category he can also select each subcategory, that is, it can be filtered by subcategory assuming I only want to see subcategories.
I have tried many ways but none works, any ideas? you can run the application in R to get an idea of what I want.
Try this
server <- function(input, output, session) {
output$selectcat <- renderUI({
selectInput("Cat", "Seleccione Categoria", choices = c("ALL",as.vector(db$CATEGORIA)))
})
output$selectsubcat <- renderUI({
req(input$Cat)
if (input$Cat=="ALL"){ df <- db
}else df <- db %>% filter(CATEGORIA %in% input$Cat)
selectInput("Subcat", "Seleccione Subcategoria", choices = c("ALL",as.vector(df$SUBCAT)))
})
activar<- reactive({
req(input$Cat,input$Subcat)
if (input$Cat=="ALL"){ df <- db
}else df <- db %>% filter(CATEGORIA %in% input$Cat)
if (input$Subcat=="ALL"){ df <- df
}else df <- df %>% filter(SUBCAT == input$Subcat)
df %>%
group_by(segment) %>%
summarise(SKUs=n(),
vta=sum(vent))
})
# Return the formula text for printing as a caption ----
output$ana_inv <- DT::renderDataTable({
activar()
})
}

How to dynamically change the values of inputs based on data from a reactive environment?

Given the following shiny code:
library(shiny)
library(data.table)
df_fr<-data.table(x1=c("a","a","a","b","b","b"),x2=c("1","1","2","2","2","3"))
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("x1", "x1", unique(df_fr$x1),multiple=T),
selectInput("x1", "x1", unique(df_fr$x2),multiple=T)
),
mainPanel( plotOutput("plot1") )
)
)
server <- function(input, output,session) {
selectedData <- reactive({
selInputs<-list(input$x1,input$x2)
req( any( !sapply(selInputs,is.null) ) | any(sapply(selInputs,is.null)) )
df_fr[(if( is.null(input$x1) ) {T} else {x1 %in% input$x1})
& (if( is.null(input$x2) ) {T} else {x2 %in% input$x2})
]
})
output$plot1 <- renderPlot({
plot(table(selectedData()))
})
}
shinyApp(ui = ui, server = server)
I want that if I choose option 'a' for 'x1' that only '1' and '2' show up as possible options for 'x2'.
The other way arround, I choose '3' for 'x2' I want that programm shows only 'b' as possible options for 'x1'. So, changing one input should restrict all other inputs to the values that are defined in the data table. Is that possible? If yes, how? I tried already an observed-block which accesses selectedData(). This did not work, unfortunatly.
Thank you! I hope my question is clear.
one way to do it is to use updateSelectInput(). Try this
library(shiny)
library(data.table)
library(ggplot2)
df_fr<-data.table(x1=c("a","a","a","b","b","b"),x2=c("1","1","2","2","2","3"))
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("x1", "x1", unique(df_fr$x1),selected=NULL, multiple=T),
selectInput("x2", "x2", unique(df_fr$x2),selected=NULL, multiple=T)
),
mainPanel( plotOutput("plot1") )
)
)
server <- function(input, output,session) {
DF <- reactiveValues(data1 = NULL,
data2 = NULL)
observe({
if (is.null(input$x1)) {
DF$data1 <- df_fr
}else DF$data1 <- df_fr[x1 %in% input$x1,]
if (is.null(input$x2)) {
DF$data2 <- df_fr
}else DF$data2 <- df_fr[x2 %in% input$x2,]
if (is.null(input$x2)){
if (is.null(input$x1)) {
updateSelectInput(session, inputId="x2", choices=unique(df_fr$x2))
}else updateSelectInput(session, inputId="x2", choices=unique(DF$data1$x2))
}
if (is.null(input$x1)){
if (is.null(input$x2)) {
updateSelectInput(session, inputId="x1", choices=unique(df_fr$x1))
}else updateSelectInput(session, inputId="x1", choices=unique(DF$data2$x1))
}
})
selectedData <- reactive({
req(input$x1,input$x2)
df_fr[(x2 %in% input$x2) & (x1 %in% input$x1),]
})
output$plot1 <- renderPlot({
req(selectedData())
ggplot(selectedData(), aes(x=x1,y=x2)) + geom_point()
})
}
shinyApp(ui = ui, server = server)

Errors in recoding variables in shiny apps

I'm trying to set codes to recode in shiny web application. However, it doesn't work for me.
Here's my code.
library(shiny)
library(rlang)
library(dplyr)
ui <- fluidPage(
titlePanel("Short Form Web App"),
sidebarPanel(
numericInput("num1","previous vector", value = NULL),
numericInput("num2","post vector", value = NULL),
selectInput("var","select Variable",names(mtcars)),
textInput("new_var","new variable names")
),
mainPanel(
verbatimTextOutput("tab1"),
verbatimTextOutput("tab2"),
actionButton("do","Do")
)
)
server <- function(input, output) {
output$tab1 <- renderPrint({
table(mtcars[["cyl"]])
})
rv <- reactiveValues(data = NULL)
rv$data <- mtcars
observeEvent(input$do,{
new_var <- input$new_var
new <- rv$data %>% transmute(!!new_var := case_when(input$var == input$num1 ~ input$num2))
rv$data <- bind_cols(rv$data,new)
output$tab2 <- renderPrint({
str(rv$data)
})
})
}
shinyApp(ui,server)
What I'm trying to do is recode previous vector to new vector like recode, but the result keeps showing NA..
Could anyone help me fix this problem?
I would very be very appreciated with your helps.
Thank you in advance.
Two issues:
As input$var is character you first have to convert to a symbol, i.e. use !!sym(input$var)
In your case_when you missed to set a default value. Hence, all values not specified to be recoded will be assigned NA.
Try this:
library(shiny)
library(rlang)
library(dplyr)
ui <- fluidPage(
titlePanel("Short Form Web App"),
sidebarPanel(
numericInput("num1","previous vector", value = NULL),
numericInput("num2","post vector", value = NULL),
selectInput("var","select Variable",names(mtcars)),
textInput("new_var","new variable names")
),
mainPanel(
verbatimTextOutput("tab1"),
verbatimTextOutput("tab2"),
actionButton("do","Do")
)
)
server <- function(input, output) {
output$tab1 <- renderPrint({
table(mtcars[["cyl"]])
})
rv <- reactiveValues(data = NULL)
rv$data <- mtcars
observeEvent(input$do,{
new_var <- input$new_var
new <- rv$data %>% transmute(!!sym(new_var) := case_when(
!!sym(input$var) == input$num1 ~ as.double(input$num2),
TRUE ~ !!sym(input$var)))
rv$data <- bind_cols(rv$data,new)
output$tab2 <- renderPrint({
str(rv$data)
})
})
}

R shiny Handsontable : use dataframe from handsontable

In the below toy example I have a data set datapred. The data set are output to an interactive table using rhandsontable. Then I covert it in a new data.frame with hot_to_r. My issue is that when I wnat to use it in my function prediction(), it send me an error message and the application crash. I don't understand why.
I'm french so I converted in english the message :
Error in as.name: the 'pairlist' object can not be automatically converted to a 'symbol' type.
library(shiny)
library(frailtypack)
library(rhandsontable)
data("readmission", package = "frailtypack")
ui <- fluidPage(
titlePanel("prediction"),
mainPanel(
fluidRow(rHandsontableOutput("hot")),
br(),
plotOutput("pred")
)
)
server <- function(input, output) {
newdata <- subset(readmission,select = c("time","event","id","dukes"))
datapred <- newdata[1,]
data <- reactive({
DF = hot_to_r(input$hot)
DF
})
model <- frailtyPenal(Surv(time,event)~cluster(id)+dukes,n.knots=10,
kappa=10000,data=readmission)
predict <- reactive(
prediction(model, data(),t=200,window=seq(50,1900,50),
MC.sample=100))
output$hot <- renderRHandsontable({
rhandsontable(datapred)
})
data <- reactive({
DF = hot_to_r(input$hot)
DF
})
output$pred <- renderPlot({
plot(predict(),conf.bands=TRUE)
})
}
shinyApp(ui = ui, server = server)
You could simply evaluate the data() first, like this. I also added some checks so you don't get other errors during the initialization
library(shiny)
library(frailtypack)
library(rhandsontable)
data("readmission", package = "frailtypack")
ui <- fluidPage(
titlePanel("prediction"),
mainPanel(
fluidRow(rHandsontableOutput("hot")),
br(),
plotOutput("pred")
)
)
server <- function(input, output) {
newdata <- subset(readmission,select = c("time","event","id","dukes"))
datapred <- newdata[1,]
data <- reactive({
hot <- input$hot
if (!is.null(hot)) hot_to_r(hot)
})
model <- frailtyPenal(Surv(time,event)~cluster(id)+dukes,n.knots=10,
kappa=10000,data=readmission)
predict <- reactive({
dat <- data()
if (!is.null(dat)) {
prediction(model, dat,t=200,window=seq(50,1900,50),
MC.sample=100)
}
})
output$hot <- renderRHandsontable({
rhandsontable(datapred)
})
output$pred <- renderPlot({
pred <- predict()
if (!is.null(pred)) plot(pred, conf.bands = TRUE)
})
}
shinyApp(ui = ui, server = server)

Using a selected row to subset another table in r shiny

I am new to using DT in R shiny.Basically what i am trying to do here is to use the select value from the first table to filter the second table.
my Ui.r is
library(shiny)
library(shinydashboard)
ui <- dashboardPage(skin="green",
dashboardHeader(title="Inventory Management"),
dashboardSidebar(disable = TRUE),
dashboardBody(fluidRow(column(4,box(status="success",
uiOutput("Firstselection"),
br(),
uiOutput("Secondselection"))
),
column(4,infoBoxOutput("salesbox")),
column(4,infoBoxOutput("Runoutbox")),
column(4,infoBoxOutput("Excessbox"))),
actionButton("actionbtn","Run"),
fluidRow(tabBox(tabPanel(
DT::dataTableOutput(outputId="table"),title = "Stock Available for the category chosen",width = 12),
tabPanel(DT::dataTableOutput(outputId="asso"),title = "Associated products",width = 12)))
))
and my server is
server <-function(input, output, session) {
observeEvent(input$actionbtn, {source('global.r',local = TRUE)
#choose sub category based on category
output$Firstselection<-renderUI({selectInput("ray",
"Category:",
c("All",unique(as.character(bestpred$lib_ray))))})
output$Secondselection<-renderUI({selectInput("sray",
"Sub Category:",
c("All",unique(as.character(bestpred[bestpred$lib_ray==input$ray,"lib_sray"]))))})
# Filter data based on selections
output$table <- DT::renderDataTable({
data <- bestpred
if (input$ray != "All"){
data <- data[data$lib_ray == input$ray,]
}
if (input$sray != "All"){
data <- data[data$lib_sray == input$sray,]
}
data
},filter="top"
)
output$salesbox<-renderInfoBox({infoBox("Total Sales",sum(data()$Total_Sales),icon = icon("line-chart"))})
output$Runoutbox<-renderInfoBox({infoBox("Total Runout",sum(data()$status=="Runout"),icon = icon("battery-quarter"))})
output$Excessbox<-renderInfoBox({infoBox("Total excess",sum(data()$status=="Excess"),icon = icon("exclamation-triangle"))})
output$asso <- DT::renderDataTable({
asso <- test1
s=data[input$tablatable_rows_selected,1]
asso <- asso[asso$num_art == s,]
asso
},filter="top")
})}
So when i select a row in the output table i wanna use that as an filter for my asso table
this code dosent poup any error but the output table asso is always empty
Find a generalized solution in the following:
Adapted from here: https://yihui.shinyapps.io/DT-rows/
library(shiny)
library(DT)
server <- shinyServer(function(input, output, session) {
output$x1 = DT::renderDataTable(cars, server = FALSE)
output$x2 = DT::renderDataTable({
sel <- input$x1_rows_selected
if(length(cars)){
cars[sel, ]
}
}, server = FALSE)
})
ui <- fluidPage(
fluidRow(
column(6, DT::dataTableOutput('x1')),
column(6, DT::dataTableOutput('x2'))
)
)
shinyApp(ui, server)

Resources