Radio button with radar plot shiny - shiny

I'm trying to make a shiny dashboard with attributes of superheros graphed in a radar plot. I'd also like to be able to use radio buttons to select which of the superheros I'd like to see in the graph. However, when I run this code, I get an error that says: Error in polygon: invalid value specified for graphical parameter "lwd". There is no lwd command that I'm aware of for radar charts so I'm not sure how to correct this. Does anyone have a suggestion on how to handle this error?
library(fmsb)
data<-data.frame(Strength = c(7, 0, 6, 7, 4, 3),
Speed = c(7, 0 , 5, 7, 3, 2),
Intelligence = c(7, 0, 6, 2, 4, 3),
Fighting_Skills = c(7, 0, 4, 4, 4, 6),
Energy = c(7, 0, 6, 6, 1, 1),
Durability = c(7, 0, 6, 6, 3, 3),
row.names = c("max", "min", "Iron Man", "Thor", "Spiderman", "Captain America"))
head(data)
colors_fill<-c(scales::alpha("gray", 0.1))
#scales::alpha("gold", 0.1),
#scales::alpha("tomato", 0.2),
#scales::alpha("skyblue", 0.2))
colors_line<-c(scales::alpha("darkgray", 0.9))
#scales::alpha("gold", 0.9),
#scales::alpha("tomato", 0.9),
#scales::alpha("royalblue", 0.9))
#radarchart(data,
#seg =7,
#title = "Radar Chart",
#pcol = colors_line,
#pfcol = colors_fill,
#plwd = 1)
#legend(x = 0.6,
#y=1.35,
#legend = rownames(data[-c(1,2),]),
# bty = "n", pch = 20, col = colors_line, cex = 1.2, pt.cex = 3)
# Define UI for application
ui <- fluidPage(
# Application title
titlePanel("Radar chart"),
# Sidebar with a radio buttons for person
sidebarLayout(
sidebarPanel(
radioButtons("variablechoice", "People Choice",
choices = c("Iron Man", "Thor", "Spiderman", "Captain America"),
selected = "Thor")
),
# Show a plot
mainPanel(
plotOutput("radar")
)
)
)
# Define server logic required to draw a radar plot
server <- function(input, output) {
output$radar <- renderPlot({
if( input$variablechoice=="Iron Man"){new<-data[c(3),] }
if( input$variablechoice=="Thor"){new<-data[c(4),] }
if( input$variablechoice=="Spiderman"){new<-data[c(5),] }
if( input$variablechoice=="Captain America"){new<-data[c(6),] }
radarchart(new,
seg = 7,
#title = "Radar Chart",
pcol = colors_line,
pfcol = colors_fill,
plwd = 0.5)
})
}
# Run the application
shinyApp(ui = ui, server = server)

The issue is that you have missed to include the first two rows of your data which contain the min and max values for the categories in your new dataframe. That's why radarchart throws an error:
library(fmsb)
library(shiny)
data <- data.frame(
Strength = c(7, 0, 6, 7, 4, 3),
Speed = c(7, 0, 5, 7, 3, 2),
Intelligence = c(7, 0, 6, 2, 4, 3),
Fighting_Skills = c(7, 0, 4, 4, 4, 6),
Energy = c(7, 0, 6, 6, 1, 1),
Durability = c(7, 0, 6, 6, 3, 3),
row.names = c("max", "min", "Iron Man", "Thor", "Spiderman", "Captain America")
)
colors_fill <- c(scales::alpha("gray", 0.1))
colors_line <- c(scales::alpha("darkgray", 0.9))
# Define UI for application
ui <- fluidPage(
# Application title
titlePanel("Radar chart"),
# Sidebar with a radio buttons for person
sidebarLayout(
sidebarPanel(
radioButtons("variablechoice", "People Choice",
choices = c("Iron Man", "Thor", "Spiderman", "Captain America"),
selected = "Thor"
)
),
# Show a plot
mainPanel(
plotOutput("radar")
)
)
)
# Define server logic required to draw a radar plot
server <- function(input, output) {
output$radar <- renderPlot({
if (input$variablechoice == "Iron Man") {
new <- data[c(1:2, 3), ]
}
if (input$variablechoice == "Thor") {
new <- data[c(1:2, 4), ]
}
if (input$variablechoice == "Spiderman") {
new <- data[c(1:2, 5), ]
}
if (input$variablechoice == "Captain America") {
new <- data[c(1:2, 6), ]
}
radarchart(new,
seg = 7,
# title = "Radar Chart",
pcol = colors_line,
pfcol = colors_fill,
plwd = 0.5
)
})
}
# Run the application
shinyApp(ui = ui, server = server)

Related

R Shiny - uiOutput causes numericInput to deselect when user is still typing in

I'm trying to create a data collection tool on R Shiny where the user can select as many categories as apply to them and then enter values for each. I've used uiOutput to allow the user to add a new category choice after clicking an action button.
For some reason, the numericInput that is created after clicking the action button will deselect after a split-second when the user is typing in a number, so it only catches one digit and you have to click it repeatedly to type in a full number.
I've tried changing the numericInput to a textInput and the same thing happens, so it's something to do with how I'm generating the uiOutput in the server, does it continually refresh and is there any way to stop it?
Example code given below, click on the new row button then try typing in the numericInput and you'll see. I have been stuck on this for ages and can't find any other questions similar so any help massively appreciated, thanks
library(tidyverse)
library(shiny)
library(shinyjs)
ui <- fluidPage(
fluidRow(wellPanel(h3("Category and quantity input"))),
wellPanel(fluidRow(column(width=4,selectInput("type0",label = h4("type"), choices= list("choice1" = 1,"choice2" = 2, "choice3"=3))),
column(width=4,numericInput("quantity0", label = h4("quantity"), value = 0, min=0)),
column(width=4,actionButton("New_row",label="Add new row"))),
uiOutput("new_row_added")
))
server <- function(input, output) {
ids <<- NULL
observeEvent(input$New_row,{
if (is.null(ids)){
ids <<- 1
}else{
ids <<- c(ids, max(ids)+1)
}
output$new_row_added <- renderUI({
tagList(
lapply(1:length(ids),function(i){
check_input_type <- paste0("type", ids[i])
check_input_quantity <- paste0("quantity", ids[i])
if(is.null(input[[check_input_type]])){
# Create a div that contains 3 new sub divs
div(fluidRow(column(width=4,
div(selectInput(paste0("type",ids[i]),label = "", choices= list("choice1" = 1,"choice2" = 2, "choice3"=3)))),
column(width=4,div(numericInput(paste0("quantity",ids[i]), label = "", value = 00, min=0))))
)
} else {
# Create a div that contains 3 existing sub divs
div(fluidRow(column(width=4,
div(selectInput(paste0("type",ids[i]),label = "", choices= list("choice1" = 1,"choice2" = 2, "choice3"=3), selected = input[[check_input_type]]))),
column(width=4,div(numericInput(paste0("quantity",ids[i]), label = "", min=0, value = input[[check_input_quantity]]))))
)
}
})
)
})
})
}
shinyApp(ui = ui, server = server)
You need to isolate input[[check_input_type]]. By doing isolate(input[[check_input_type]]). If not, every time a new number is inserted inside that input, the ui will re render and cause the deselection.
App:
library(tidyverse)
library(shiny)
library(shinyjs)
ui <- fluidPage(
fluidRow(wellPanel(h3("Category and quantity input"))),
wellPanel(
fluidRow(
column(width = 4, selectInput("type0", label = h4("type"), choices = list("choice1" = 1, "choice2" = 2, "choice3" = 3))),
column(width = 4, numericInput("quantity0", label = h4("quantity"), value = 0, min = 0)),
column(width = 4, actionButton("New_row", label = "Add new row"))
),
uiOutput("new_row_added")
)
)
server <- function(input, output) {
ids <<- NULL
observeEvent(input$New_row, {
if (is.null(ids)) {
ids <<- 1
} else {
ids <<- c(ids, max(ids) + 1)
}
output$new_row_added <- renderUI({
tagList(
lapply(1:length(ids), function(i) {
check_input_type <- paste0("type", ids[i])
check_input_quantity <- paste0("quantity", ids[i])
if (is.null(isolate(input[[check_input_type]]))) {
# Create a div that contains 3 new sub divs
div(fluidRow(
column(
width = 4,
div(selectInput(paste0("type", ids[i]), label = "", choices = list("choice1" = 1, "choice2" = 2, "choice3" = 3)))
),
column(width = 4, div(numericInput(paste0("quantity", ids[i]), label = "", value = 00, min = 0)))
))
} else {
# Create a div that contains 3 existing sub divs
div(fluidRow(
column(
width = 4,
div(selectInput(paste0("type", ids[i]), label = "", choices = list("choice1" = 1, "choice2" = 2, "choice3" = 3), selected = isolate(input[[check_input_type]])))
),
column(width = 4, div(numericInput(paste0("quantity", ids[i]), label = "", min = 0, value = input[[check_input_quantity]])))
))
}
})
)
})
})
}
shinyApp(ui = ui, server = server)

How can I plot the model output in shiny

This is the output, that I would like to plot with shiny.
<constr <- c(+4,-3,-2,-5)
# Uhlig rejection
model1s <- uhlig.reject(Y=uhligdata, nlags=12, draws=200, subdraws=200, nkeep=100, KMIN=1,
KMAX=5, constrained = constr, constant=FALSE, steps=60)
irf1s <- model1s$IRFS
irfplot(irf1s)
# Uhlig penalty
model1d <- uhlig.penalty(Y=uhligdata, nlags=12, draws=200, subdraws=1000,nkeep=100, KMIN=1, KMAX=5, constrained=constr,
constant=FALSE, steps=60, penalty=100, crit=0.001)
irf1d <- model1d$IRFS
irfplot(irf1d)>
and below is my attemp. I am trying to have the test, lags and periods dynamic and based on them to have the IRFs plotted.
ui <- dashboardPage(
dashboardHeader(title = "НАЧАЛО"),
dashboardSidebar(
sidebarMenu(
menuItem("BVAR",
tabName = "test_tab",
icon = icon("dashboard"))
)
),
dashboardBody(
tabItems(
tabItem(tabName = "test_tab",
box(column(10,
radioButtons("test1",
label = "Изберете тест",
choices = c("Uhlig rejection", "Uhlig penalty")),
numericInput("nlags", "NLAGS", min = 1, max = 20, value = 1, step = 1),
numericInput("kmin", "KMIN", min = 1, max = 10, value = 1, step = 1),
numericInput("kmax", "KMAX", min = 2, max = 10, value = 2, step = 1),
submitButton("Submit"))),
box(column(12,
plotOutput("plot2",8))),)
)
))
server <- function(input, output){
modelselect <- reactive({
if(input$test1 == "Uhlig Rejection"){
fit <- uhlig.reject(uhligdata, nlags = input$nlags,constrained = constr, KMIN = input$kmin, KMAX = input$kmax)
return(fit)
}else
if(input$test1 == "Uhlig Penalty"){
fit <- uhlig.penalty(uhligdata,nlags = input$nlags, KMIN = input$kmin, KMAX = input$kmax)
return(fit)
}
})
myplot1 <- reactive({
if(input$test1 == "Uhlig Rejection"){
irfs <- modelselect()$IRFS
irfs} else
if(input$test1 == "Uglig Penalty"){
irfs <-modelselect()$IRFS
irfs}
})
output$plot2 <- renderPlot({
irfplot(myplot1())
})
}
shinyApp(ui = ui, server = server)
The dashboard loads fine but I cannot access the IRF plot. I wonder if the problem is with the reactive function or I do not access the model output correctly(I am quite a newbie to shiny)?

Shiny tabPanel datatable including filter options

I have created a tabPanel and want to give the chance to filter by different variables (e.g., show All, gender (male or female), gaming frequency (never, sometimes, often). Giving a filter possibility on the right side of the table.
The tabPanel alone is working fine, however, I do not know how to add the select Input filter (a) multiple variables as well as b) used the output$data for output$mytable.
Gender <- c(2, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1) # 1 male, 2 female
Gaming_freq <- c(2, 3, 3, 3, 6, 4, 5, 5, 3, 5, 6, 5, 3, 3, 3, 2, 5, 6, 6, 3) # 2 = less than once a month, 3= once a month, 4 = once a week, 5 = more than once a week, 6 = daily
color_white <- c(0.14939, -0.40033, 0.638, -0.40328, -0.5725, 0.77422, 0.47419, -0.14982, 0.61388, 0.29264, 1.63992, 1.69396, -0.76722, 0.2279, 1.8937, 1.05535, -0.02912, -0.98787, -0.08184, 0.02536)
color_black_red <- c(-0.22686, 1.0993, 1.31564, 1.79799, 0.58323, -0.20128, 0.28315, 0.65687, -0.28894, 1.03393, 0.19963, -0.14561, 0.889, 1.5685, 0.15463, 0.74984, 0.42837, 1.31831, 0.82064, 1.13308)
color_black_blue <- c(-0.19905, -0.12332, -0.3628, 0.04108, -0.51553, -0.74827, -0.73246, -1.15794, -1.05443, -0.79687, -0.43895, -0.48986, -0.25574, -1.55343, -0.52319, -0.31203, -0.62926, -1.0094, -0.11217, -0.76892)
Controller_none <- c(-0.83456, -2.1176, -2.09919, -2.30543, -1.8594, -1.83014, -2.67447, -2.25647, -0.33004, 1.04676, -0.0674, -1.22428, -0.61644, -2.49707, 0.1737, -1.38711, -0.86417, -0.9775, -0.86747, -0.13341)
Controller_white <- c(0.51451, 0.49362, 1.17843, -0.03151, 1.27484, 0.74152, 0.07918, 1.18577, 0.50183, -0.1483, 0.22328, 1.1426, 0.46526, 1.94735, -0.60943, 1.02407, 0.55938, 1.10468, -0.12908, -0.00329)
Controller_red <- c(0.93577, 1.92379, 0.8746, 1.02084, 1.08547, 0.74312, 1.53032, 0.74821, -0.10777, 0.48774, 0.29206, 0.09947, 0.21528, 1.41961, 1.59125, -0.21777, 0.56455, 0.83702, 1.2306, 0.51277)
All <- rep(1, 20)
d <- as.data.frame(cbind(Gender, Gaming_freq, color_white, color_black_red, color_black_blue, Controller_none, Controller_white, Controller_red, All))
library(shiny)
library(shinythemes)
library(shinydashboard)
ui <- fluidPage(theme = shinytheme("sandstone"),
dashboardPage(skin = "red",
header = dashboardHeader(title = "Dashboard of Survey Results"),
sidebar = dashboardSidebar(
sidebarMenu(
menuItem("Overview", tabName = "overview", icon = icon("dashboard")),
menuItem("Utilities", icon = icon("th"), tabName = "utilities"),
menuItem("Importances", icon = icon("th"), tabName = "importances")
)
),
body = dashboardBody(tabItems(
tabItem(tabName = "utilities",
h2("Utilities of attribute levels"),
mainPanel(
tabsetPanel(
id = 'dataset',
tabPanel("Color", DT::dataTableOutput("mytable1")),
tabPanel("Extra Controller", DT::dataTableOutput("mytable2"))
)
)),
tabItem(tabName = "importances",
h2("Importance for attributes")
))))
)
server <- function(input, output) {
output$mytable1 <- DT::renderDataTable({
DT::datatable(round(d[,3:5], digits = 3), options = list(lengthMenu = c(5, 30, 50, 90), pageLength = 10, bFilter=0))
})
output$mytable2 <- DT::renderDataTable({
DT::datatable(round(d[,6:8], digits = 3),options = list(lengthMenu = c(5, 30, 50, 90), pageLength = 10, bFilter=0))
})
}
shinyApp(ui = ui, server = server)
Thanks in advance.
You can filter your data and wrap it in a reactive element, so you can later use it for any subsequent output plots/tables. You can read more about working with reactive expressions on Rstudio website.
Here as a demo, I get an input on the 'Gender', for further filtering the data out (I've used radio buttons but you can use your widget of choice: slider, select button, etc.)
radioButtons("gender", "filter for gender",
choices = c("One" = '1',
"Two" = '2')),
Then in the server, I use this input to filter the data based on the gender, and wrap it up in a reactive element:
filteredData <- reactive({
tempDataTable <- d %>% dplyr::filter(Gender==input$gender)
tempDataTable
})
Next you can use this reactive element containing your filtered data for generating output tables:
output$mytable1 <- DT::renderDataTable({
d <- filteredData()
DT::datatable(round(d[,3:5], digits = 3), options = list(lengthMenu = c(5, 30, 50, 90), pageLength = 10, bFilter=0))
})
You can use similar strategy to add additional filters or features, find the entire demo ui+server code here:
library(shiny)
library(shinythemes)
library(shinydashboard)
library(tidyverse)
library(DT)
ui <- fluidPage(theme = shinytheme("sandstone"),
dashboardPage(skin = "red",
header = dashboardHeader(title = "Dashboard of Survey Results"),
sidebar = dashboardSidebar(
sidebarMenu(
menuItem("Overview", tabName = "overview", icon = icon("dashboard")),
menuItem("Utilities", icon = icon("th"), tabName = "utilities"),
menuItem("Importances", icon = icon("th"), tabName = "importances")
)
),
body = dashboardBody(tabItems(
tabItem(tabName = "utilities",
h2("Utilities of attribute levels"),
mainPanel(
radioButtons("gender", "filter for gender",
choices = c("One" = '1',
"Two" = '2')),
tabsetPanel(
id = 'dataset',
tabPanel("Color", DT::dataTableOutput("mytable1")),
tabPanel("Extra Controller", DT::dataTableOutput("mytable2"))
)
)),
tabItem(tabName = "importances",
h2("Importance for attributes")
))))
)
server <- function(input, output) {
filteredData <- reactive({
tempDataTable <- d %>% dplyr::filter(Gender==input$gender)
tempDataTable
})
output$mytable1 <- DT::renderDataTable({
d <- filteredData()
DT::datatable(round(d[,3:5], digits = 3), options = list(lengthMenu = c(5, 30, 50, 90), pageLength = 10, bFilter=0))
})
output$mytable2 <- DT::renderDataTable({
d <- filteredData()
DT::datatable(round(d[,6:8], digits = 3),options = list(lengthMenu = c(5, 30, 50, 90), pageLength = 10, bFilter=0))
})
}
shinyApp(ui = ui, server = server)

Is it possible to filter a simple feature (sf) object using selectizeGroupUI in R shiny?

I'm trying to build a Shiny app containing a leaflet map showing movement paths, that can be bidirectionally filtered using two other columns in the dataset which contains the geometry data.
To do so, I'm trying to use selectizeGroupUI (shinyWidgets package), which allows bidirectional/mutually dependent filtering.
However, when I run the code I get the following error:
"Warning: Error in polygonData.default: Don't know how to get path
data from object of class data.frame"
I have a feeling that this is because mapping path (linestring) data in a leaflet map requires the underlying dataset to be an sf object, whereas selectizeGroupUI converts the sf object into a data.table(?), hence the error message.
This is supported by the fact that when I convert the dataset from sf object to data.table and try to plot the paths as individual A and B coordinates (without a connecting line), the whole thing works perfectly.
Any idea whether there exists a work around?
Any help would be hugely appreciated, please and thanks!
A reprex:
library(tidyverse)
library(sf)
library(shiny)
library(shinyWidgets)
# generate the table with geometry data
geo_data <- structure(list(idx = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
start_lat = c(33.40693,33.64672, 33.57127, 33.42848, 33.54936, 33.53418, 33.60399, 33.49554,33.5056, 33.61696),
start_long = c(-112.0298, -111.9255, -112.049,-112.0998, -112.0912, -112.0911, -111.9273, -111.9687, -112.0563, -111.9866),
end_lat = c(33.40687, 33.64776, 33.57125, 33.42853,33.54893, 33.53488, 33.60401, 33.49647, 33.5056, 33.61654),
end_long = c(-112.0343,-111.9303, -112.0481, -112.0993, -112.0912, -112.0911, -111.931,-111.9711, -112.0541, -111.986)),
row.names = c(NA, -10L), spec = structure(list(cols = list(idx = structure(list(), class = c("collector_double","collector")),
start_lat = structure(list(), class = c("collector_double", "collector")),
start_long = structure(list(), class = c("collector_double", "collector")),
end_lat = structure(list(), class = c("collector_double", "collector")),
end_long = structure(list(), class = c("collector_double","collector"))),
default = structure(list(), class = c("collector_guess","collector")), delim = ","),
class = "col_spec"),class = c("data.table","data.frame"))
geo_data<- setDT(geo_data)
geo_data <- geo_data[
, {
geometry <- sf::st_linestring(x = matrix(c(start_lat, start_long, end_long, end_long), ncol = 2, byrow = T))
geometry <- sf::st_sfc(geometry)
geometry <- sf::st_sf(geometry = geometry)
}
, by = idx
]
# generate the table with columns to filter the geometry data, join with geometry data and convert to sf
table <- structure(list(idx = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
column1 = c("A", "A", "A", "B", "B", "B", "C", "C", "C", "C"),
column2 = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)), row.names = c(NA, -10L),
class = c("tbl_df","tbl", "data.frame")) %>%
left_join(x = ., y = geo_data, by = "idx", keep = FALSE)
sf <- sf::st_as_sf(table)
# Shiny
ui <- fluidPage(
fluidRow(
column(
width = 10, offset = 1,
tags$h3("Filter data with selectize group"),
panel(
selectizeGroupUI(
id = "my-filters",
params = list(
column1 = list(inputId = "column1", title = "column1:"),
column2 = list(inputId = "column2", title = "column2:")
)
), status = "primary"
),
leafletOutput(outputId = "map")
)
)
)
server <- function(input, output, session) {
res_mod <- callModule(
module = selectizeGroupServer,
id = "my-filters",
data = sf,
vars = c("column1", "column2"))
output$map <- renderLeaflet({
leaflet() %>%
addPolylines(data = res_mod())
})
}
shinyApp(ui, server)
When res_mod() is called, it returns a data.frame but you can coerce it back again using st_as_sf() like any other dataframe object that has a geometry column in it.
output$map <- renderLeaflet({
leaflet() %>%
addPolylines(data = st_as_sf(res_mod()))
})
After that output$map starts working again.

Save and Load user selections based on file selection - RShiny

I am trying to create simple app that acts as a GUI for studying different files having same variables but with different version and content. I am unable to give an app where every time the user opens the app they dont have to enter in their parameters again where they left off. I'd like them to be able to save their parameters and bring them up again when they go back to the app.
I am giving my sample code here, however the number of inputs and plots are far more in the actual app. I want to know if there is any solution to save these dependent inputs and outputs.
library(shiny)
library(pryr)
ui = shinyUI(fluidPage(
# Application title
titlePanel("Example Title"),
# Sidebar structure
sidebarLayout(
sidebarPanel(
textInput("save_file", "Save to file:", value="sample.RData"),
actionButton("save", "Save input value to file"),
uiOutput("load"),
uiOutput("file"),
uiOutput("mytype"),
uiOutput("mysubtype")
),
# Show a plot of the generated distribution
mainPanel(
tabsetPanel(id="tab",
tabPanel(
"Plot",
plotOutput("distPlot"),
checkboxInput(inputId = "density",
label = strong("Show Adjustment Factors"),
value = FALSE),
conditionalPanel(condition = "input.density == true",
sliderInput(inputId = "bandwidth",
label = "Width adjustment: ",
min = 0.5, max = 4, value = 1, step = 0.1),
radioButtons("mycolor", "Color Adjustment: ",
choices = c(Red = "red", Black = "black", Blue = "blue"),selected = "black", inline = TRUE)
)),
tabPanel("Summary",
h3(textOutput("label")),
verbatimTextOutput("summary")
)
))
)
)
)
server = function(input, output, session) {
# render a selectInput with all RData files in the specified folder
output$load <- renderUI({
choices <- list.files("/home/user/Documents/Shiny/", pattern="*.RData")
selectInput("input_file", "Select input file", choices)
})
# render a selectInput with all csv files in the specified folder so that user can choose the version
output$file <- renderUI({
choices.1 <- list.files("/home/user/Documents/Shiny/", pattern="*.csv")
selectInput("input_csv", "Select csv file", choices.1)
})
# Load a csv file and update input
data = eventReactive(input$input_csv, {
req(input$input_csv)
read.csv(paste0("/home/user/Documents/Shiny/",input$input_csv),
header = TRUE,
sep = ",")
})
#Display Type - Types may differ based on file selection
output$mytype <- renderUI({
selectInput("var1", "Select a type of drink: ", choices = levels(data()$Type))
})
#Display SubType - This would be dependent on Type Selection
output$mysubtype <- renderUI({
selectInput("var2", "Select the SubType: ", choices = as.character(data()[data()$Type==input$var1,"Subtype"]))
})
# Save input when click the button
observeEvent(input$save, {
validate(
need(input$save_file != "", message="Please enter a valid filename")
)
mycolor <- input$mycolor
mytype = input$var1
mysubtype = input$var2
density <- input$density
bandwidth <- input$bandwidth
save(bandwidth, density, mycolor, mytype, mysubtype,
file=paste0("/home/user/Documents/Shiny/", input$save_file))
choices <- list.files("/home/user/Documents/Shiny/", pattern="*.RData")
updateSelectInput(session, "input_file", choices=choices)
choices.1 <- list.files("/home/user/Documents/Shiny/", pattern="*.csv")
updateSelectInput(session, "input_csv", choices=choices.1)
})
# Load an RData file and update input
# input$var1, input$var2, input$density, input$bandwidth, input$mycolor),
observeEvent(c(input$input_file),
{
load(paste0("/home/user/Documents/Shiny/",input$input_file))
updateSelectInput(session, "var1", choices = levels(data()$Type), selected = mytype)
updateSelectInput(session, "var2", choices = as.character(data()[data()$Type==mytype,"Subtype"]), selected = mysubtype)
updateCheckboxInput(session, "density", value = density)
updateSliderInput(session, inputId = "bandwidth", value=bandwidth)
updateRadioButtons(session, "mycolor", choices = c(Red = "red", Black = "black", Blue = "blue"), selected = mycolor, inline = TRUE)
})
output$distPlot <- renderPlot({
# generate plot
x = data()[data()$Type == input$var1 & data()$Subtype == input$var2, c("Alcohol_Content","Price")]
plot(x$Alcohol_Content, x$Price, type = "l", xlab = "Alcohol content", ylab = "Price",
main = "Sample Plot",
col="red",
lwd=1.5)
if (input$density)
plot(x$Alcohol_Content, x$Price, type = "p", xlab = "Alcohol content", ylab = "Price",
main = "Sample Plot",
col=input$mycolor,
lwd=input$bandwidth)
})
output$summary <- renderText(summary(data()))
}
shinyApp(ui, server)
The Input csv files would be always stored in
"/home/user/Documents/Shiny/"
The User could just click "Save to
file:" and it should save the user selections inside "sample.RData"
located in same "/home/user/Documents/Shiny/". Hence I want to give a selectinput where user can choose the .RData file also.
The user should also be able to save the inputs on Mainpanel which they would use to modify the chart
Questions:-
Most of the code works fine given above but how can I save #Display Subtype.
What happens if I add one more dependent list like Type and Subtype?
And also if I can get some help on whether the solution would work for multiple select inputs?.
Any help on the code would be really be appreciated.
Dummy Data:-
x = data.frame(Type=rep(c("WINE"), 9), Subtype=rep(c("TABLE WINE RED", "TABLE WINE WHITE", "MONTILLA"), each=3), Alcohol_content= c(14, 11.5, 12, 11, 13.5, 11, 12.5, 12, 11.5), Price = c(30.99, 32.99, 29.99, 33.99, 36.99, 34.99, 119, 32.99, 13.99))
y = data.frame(Type=rep(c("REFRESHMENT"), 9), Subtype=rep(c("CIDER ALL", "SPIRIT", "BEER"), each=3), Alcohol_content= c(5, 5.2, 7, 5.3, 6.9, 5, 5, 6, 5), Price = c(9.99, 9.99, 8.99, 9.95, 3.49, 9.99, 12.99, 13.49, 21.99))
bcl_data1 = rbind(x, y)
write.csv(bcl_data1, "bcl_data1.csv")
There are many more Subtypes under each Type (Wine , Refreshment). I am somehow not able to retrieve the Subtype value through above code, However when I load Sample.RData I can see var2 = my selected value.
I would like to know how save these values please.
Here is a working version of your code. Your problem was the concurrent use of renderUI and updateSelectInput. Everytime you tried to update your selectInput it was re-rendered right away so that the change wasn't visible.
I'd recommend to render the selectInput's in the UI (which I did for "var2") and use updateSelectInput only. (If you really want to continue building your own bookmarks.)
Best regards
library(shiny)
library(pryr)
if(!file.exists("bcl_data1.csv")){
x = data.frame(Type=rep(c("WINE"), 9), Subtype=rep(c("TABLE WINE RED", "TABLE WINE WHITE", "MONTILLA"), each=3), Alcohol_content= c(14, 11.5, 12, 11, 13.5, 11, 12.5, 12, 11.5), Price = c(30.99, 32.99, 29.99, 33.99, 36.99, 34.99, 119, 32.99, 13.99))
y = data.frame(Type=rep(c("REFRESHMENT"), 9), Subtype=rep(c("CIDER ALL", "SPIRIT", "BEER"), each=3), Alcohol_content= c(5, 5.2, 7, 5.3, 6.9, 5, 5, 6, 5), Price = c(9.99, 9.99, 8.99, 9.95, 3.49, 9.99, 12.99, 13.49, 21.99))
bcl_data1 = rbind(x, y)
write.csv(bcl_data1, "bcl_data1.csv")
}
settings_path <- getwd()
# settings_path <- "/home/user/Documents/Shiny/"
ui = shinyUI(fluidPage(
# Application title
titlePanel("Example Title"),
# Sidebar structure
sidebarLayout(
sidebarPanel(
textInput("save_file", "Save to file:", value="sample.RData"),
actionButton("save", "Save input value to file"),
p(),
p(),
uiOutput("load"),
uiOutput("file"),
uiOutput("mytype"),
selectInput("var2", "Select the SubType: ", choices = NULL)
),
# Show a plot of the generated distribution
mainPanel(
tabsetPanel(id="tab",
tabPanel(
"Plot",
plotOutput("distPlot"),
checkboxInput(inputId = "density",
label = strong("Show Adjustment Factors"),
value = FALSE),
conditionalPanel(condition = "input.density == true",
sliderInput(inputId = "bandwidth",
label = "Width adjustment: ",
min = 0.5, max = 4, value = 1, step = 0.1),
radioButtons("mycolor", "Color Adjustment: ",
choices = c(Red = "red", Black = "black", Blue = "blue"),selected = "black", inline = TRUE)
)),
tabPanel("Summary",
h3(textOutput("label")),
verbatimTextOutput("summary")
)
))
)
)
)
server = function(input, output, session) {
# render a selectInput with all RData files in the specified folder
last_save_path <- file.path(settings_path, "last_input.backup")
if(file.exists(last_save_path)){
load(last_save_path)
if(!exists("last_save_file")){
last_save_file <- NULL
}
} else {
last_save_file <- NULL
}
if(!is.null(last_save_file)){
updateTextInput(session, "save_file", "Save to file:", value=last_save_file)
}
output$load <- renderUI({
choices <- list.files(settings_path, pattern="*.RData")
selectInput("input_file", "Select input file", choices, selected = last_save_file)
})
# render a selectInput with all csv files in the specified folder so that user can choose the version
output$file <- renderUI({
choices.1 <- list.files(settings_path, pattern="*.csv")
selectInput("input_csv", "Select csv file", choices.1)
})
# Load a csv file and update input
csv_data = eventReactive(input$input_csv, {
req(input$input_csv)
read.csv(file.path(settings_path,input$input_csv),
header = TRUE,
sep = ",")
})
#Display Type - Types may differ based on file selection
output$mytype <- renderUI({
req(csv_data())
selectInput("var1", "Select a type of drink: ", choices = unique(csv_data()$Type))
})
#Display SubType - This would be dependent on Type Selection
observeEvent(input$var1, {
req(csv_data())
req(input$var1)
updateSelectInput(session, "var2", "Select the SubType: ", choices = as.character(csv_data()[csv_data()$Type==input$var1,"Subtype"]), selected = isolate(input$var2))
})
# Save input when click the button
observeEvent(input$save, {
validate(
need(input$save_file != "", message="Please enter a valid filename")
)
last_save_file <- input$save_file
save(last_save_file, file=last_save_path)
mycolor <- input$mycolor
mytype = input$var1
mysubtype = input$var2
density <- input$density
bandwidth <- input$bandwidth
save(bandwidth, density, mycolor, mytype, mysubtype,
file=file.path(settings_path, input$save_file))
})
# Load an RData file and update input
observeEvent(input$input_file, {
req(input$input_file)
load(file.path(settings_path, input$input_file))
updateSelectInput(session, "var1", choices = unique(csv_data()$Type), selected = mytype)
updateSelectInput(session, "var2", choices = mysubtype, selected = mysubtype)
updateCheckboxInput(session, "density", value = density)
updateSliderInput(session, "bandwidth", value = bandwidth)
updateRadioButtons(session, "mycolor", choices = c(Red = "red", Black = "black", Blue = "blue"), selected = input$mycolor)
})
output$distPlot <- renderPlot({
req(csv_data())
req(input$var1)
req(input$var2)
# generate plot
x = csv_data()[csv_data()$Type == input$var1 & csv_data()$Subtype == input$var2, c("Alcohol_content", "Price")]
if(nrow(x) > 0){
x <- x[order(x$Alcohol_content), ]
plot(x$Alcohol_content, x$Price, type = "l", xlab = "Alcohol content", ylab = "Price",
main = "Sample Plot",
col="red",
lwd=1.5)
if (input$density)
plot(x$Alcohol_content, x$Price, type = "p", xlab = "Alcohol content", ylab = "Price",
main = "Sample Plot",
col=input$mycolor,
lwd=input$bandwidth)
}
})
output$summary <- renderText(summary(csv_data()))
}
shinyApp(ui, server)