How to delete dynamic drop down button in shiny - dynamic

'''I have just provided manual choices to the data frame and created the drop down button for them which contains a action button(delete) inside it so on clicking delete action button i want to delete that drop down but not getting how to achieve this'''
library(shiny)
library(shinyWidgets)
ui <- fluidPage(
column(1,
uiOutput("moreControls")
)
)
server <- function(input, output) {
output$moreControls <- renderUI({
mat <- as.data.frame(c("Flow Rate (10NHPA.PV) (L/m)","Flow Rate (10NHPA.PV) (L/m)","Flow Rate (10NHPA.PV) (L/m)","Flow Rate (10NHPA.PV) (L/m)","Flow Rate (10NHPA.PV) (L/m)"),stringsAsFactors = FALSE)
buttons <- lapply(1:nrow(mat), function(i)
{
btName <- paste0(mat[i,1])
fluidRow(
br(),
column(2,
dropdownButton(inputId=btName,label=paste(mat[i,1]),circle = F, status = "primary", icon = icon("circle"), width = "300px",
actionButton(inputId="toggle",label = "Delete"))
)
)
})
observeEvent(input$toggle, { removeUI(selector='#btName', immediate=TRUE)}, autoDestroy=TRUE)
return(buttons)
#observeEvent(input$toggle, {removeUI(selector = "#btName")})
})
}
shinyApp(ui, server)

Related

What is the easiest way to add a tooltip to a boxplot(ggplot) generated through Shiny?

I need the y-value displayed in a tooltip-style text box when the cursor hovers over a bar. I have to imagine this is a simple function through Shiny, but I haven't been able to figure it out.
I'll include the relevant UI and server code below:
UI :
#TAB 3 (QUOTA/SALES)
tabPanel(title = "Quota/Sales",
fluidRow(column(9,
wellPanel(height=600, width ="100%",
plotOutput("quota", height=550, width ="100%"
))),
column(3,
wellPanel(height=100, width ="100%",
selectInput("countyquota", "County:", choices=countychoices, selected = "Statewide"))))
)))
Server:
hdata <- reactive({
if(input$sexage == "All" & input$countyharv == "Statewide") {
harvdata}
else if(input$sexage == "All" & input$countyharv != "Statewide")
{filter(harvdata, NAME == input$countyharv)}
else if (input$sexage != "All" & input$countyharv != "Statewide")
{filter(harvdata, sexage == input$sexage, NAME == input$countyharv)}
else if (input$countyharv == "Statewide" & input$sexage != "All"){
filter(harvdata, sexage == input$sexage)
}
})
output$harv <- renderPlot({
ggplot(hdata(), aes(fill=sexage, y=harvest, x=year, label = harvest)) +
geom_bar(position="dodge", stat="identity") +
xlab("Year") +
ylab("Harvest") +
labs(fill = NULL)+
theme_bw()
})`
Welcome to StackOverflow. The first thing is that it is always a good idea to include a minimal reproducible example of your base code. That way you help us to help you. In your case, the code you provide does not run (is not reporducible) you have to include the data (or a sample).
Going into the answer. ggplot2 output by default does not show tooltip, you need to use a JavaScript base library for that. The more common are plotly and highcharter.
Lets create a shiny app using the mtcars dataset to show you how to take ggplot2 plots to plotly using the plotly::ggplotly() function.
Note the important comments within the code.
library(shiny)
library(plotly) # you need this packages
ui <- fluidPage(
selectInput('x', 'X axis', choices = names(mtcars), selected = 'wt'),
selectInput('y', 'Y axis', choices = names(mtcars), selected = 'mpg'),
fluidRow(
column(
width = 6,
plotOutput('static'),
),
column(
width = 6,
# New function to render plotly outputs
plotlyOutput('dynamic')
)
)
)
server <- function(input, output, session) {
# This a regular ggplot2 object.
plot <- reactive({
ggplot(
data = mtcars,
mapping = aes(x = .data[[input$x]], y = .data[[input$y]])
) +
geom_point() +
theme_bw()
})
output$static <- renderPlot({ plot() })
# 1- New render frunction to handel plotly outputs
# 2- Place a ggplot2 object within the ggplotly() function
output$dynamic <- renderPlotly({ ggplotly(plot()) })
}
shinyApp(ui, server)

Reactive or observe in dynamic filtering

I have a working app that uses multiple filters to plot some data and i want the filters to be dynamic and dependent on the filter above by only showing available options for the selection. For instance if the Location_Id == 1 then only 'Bike' User_Type is available in the 'User Type' filter. This all works when the app starts with the filters all constrained by the initial Location_ID starting value but as soon as i change the initial input (Location_Id) nothing is getting updated automatically and i have to do an Select All to see which data is available for the new selected Location Id. I have been reading all morning and it seems i need to perhaps include a reactive() somewhere in the server but its not clear how then i update the ui and if i need a render type function somewhere.
#Example for stack overflow
library(shiny)
library(datasets)
library(dplyr)
library(shinyWidgets)
library(lubridate)
#Create test data
set.seed(10)
Dates. <- sample(c(seq(as.Date("2017-01-01"),as.Date("2017-12-28"),1),seq(as.Date("2018-01-01"),as.Date("2019-12-28"),1)),1000)
Facility_Type. <- sample(c("Bikelane","No facility"),length(Dates.),replace = T)
Data.. <- data.frame(Date = Dates., Facility_Type = Facility_Type.)
Data..$User_Type_Desc<- sample(c("Bike","Pedestrian"),nrow(Data..),replace = T)
Data..$Counts <- sample(1:100,nrow(Data..),replace = T)
Data..$Location_Id <- sample(c("01","02","03","04"),nrow(Data..),replace = T)
Data..$Month <- months(Data..$Date)
Data..$Year <- year(Data..$Date)
Data..$User_Type_Desc <- as.character(Data..$User_Type_Desc)
Data..$Facility_Type <- as.character(Data..$Facility_Type)
#Force some changes on data to highlight problem
Data..$User_Type_Desc[Data..$Location_Id%in%"01"] <- "Bike"
Data..$User_Type_Desc[Data..$Location_Id%in%"04"] <- "Pedestrian"
ui <-
#shinyUI(fluidPage(
navbarPage(title = "Bend Bike/PedTraffic Counts",
#Graphics panel
tabPanel("Charting",
#headerPanel(title = "Bend Traffic Count Data Viewer"),
sidebarLayout(
sidebarPanel(
#Select Location Id
selectInput("Location_Id","Select a Location Id",choices = unique(Data..$Location_Id)),
#Select Year
pickerInput(inputId = "Year", label = "Select/deselect all + format selected", choices = NULL,
options = list(`actions-box` = TRUE, size = 10,`selected-text-format` = "count > 3"), multiple = TRUE),
#Select Month
pickerInput(inputId = "Month", label = "Select/deselect all + format selected", choices = NULL,
options = list(`actions-box` = TRUE, size = 10,`selected-text-format` = "count > 3"), multiple = TRUE),
#Location details
##################
#Select User Types
pickerInput(inputId = "User_Type", label = "Select/deselect all + format selected", choices = NULL,
options = list(`actions-box` = TRUE, size = 10,`selected-text-format` = "count > 3"), multiple = TRUE),
#Select Facility Types
pickerInput(inputId = "Facility_Type", label = "Select/deselect all + format selected", choices = NULL,
options = list(`actions-box` = TRUE, size = 10,`selected-text-format` = "count > 3"), multiple = TRUE)
#dateRangeInput("Date", "Input date range")
#selectInput("Date","Select a Product",choices = NULL)
#Panel end
),
mainPanel( plotOutput("location_plot"))
#Sidebar panel layout end
)
# Sidebar panel end
)
#PAge end
)
server <-
#print(str(product_list))
shinyServer(function(session,input,output) {
#Create selection menus
##########################
#Year selection with choices constrained by Location_Id
observe({
Years. <- unique(Data..$Year[Data..$Location_Id%in%input$Location_Id])
updatePickerInput(session,"Year","Select Year(s)",choices = Years.,selected = Years.[1])
})
#Month selection with Year choices
observe({
Months. <- unique(Data..$Month[Data..$Year%in%input$Year])
updatePickerInput(session,"Month","Select Month(s)",choices = Months., selected = Months.[1] )
})
#User Type
observe({
User_Type. <- unique(Data..$User_Type_Desc[Data..$Year%in%input$Year & Data..$Month%in%input$Month])
updatePickerInput(session,"User_Type","Select User Type(s)",choices = User_Type., selected = User_Type.[1])
})
#Facility Type
observe({
Facility_Type. <- unique(Data..$Facility_Type[Data..$Year%in%input$Year & Data..$Month%in%input$Month
& Data..$User_Type_Desc%in%input$User_Type])
updatePickerInput(session,"Facility_Type","Select Facility Type(s)",choices = Facility_Type., selected = Facility_Type.[1])
})
#Plot data
##########################
#Select final data and chart
output$location_plot <- renderPlot({
#Select data
dat <- Data..[Data..$Location_Id%in%input$Location_Id & Data..$Month%in%input$Month &
Data..$Year%in%input$Year & Data..$User_Type_Desc%in%input$User_Type,]
#Initialze chart
ggplot(data = dat, x=Date, y = Counts) +
geom_bar(aes(x = Date,y = Counts),color = "black", position = "dodge", stat = "identity")+
facet_wrap(Facility_Type~User_Type_Desc)
})
})
#Run App
shinyApp(ui,server)
I have developed a solution for the above problem that started this issue (making filters update with proper reactive-ness) but now that i have added a map the app tends to break after making selections in the first selector, in this example that would be the state.
I created a new example below that answers the above question but poses a new one: Why is my app crashing and does it have to do with improper way i handle the reactive-ness?
In order to get the app to crash you have to select a couple of different states and let it render. It seems to do it on California so it makes me wonder if its a matter of the amount of data the map is attempting to render. Unfortunately there is no error given RStudio just crashes. Not sure if this is the proper way to pose this question but if the reactive-ness is the problem with the RStudio crash i think its still relevant to this thread. Thx for any help!
library(shiny) # for shiny apps
library(ggplot2)
library(plotly)
library(dplyr)
library(shinyWidgets)
library(tigris)
library(mapview)
library(leaflet)
library(raster)
library(rgeos)
# Load(Create) data
State_01_Tracts_Sp <- tracts("01")
State_02_Tracts_Sp <- tracts("02")
State_04_Tracts_Sp <- tracts("04")
State_05_Tracts_Sp <- tracts("05")
State_06_Tracts_Sp <- tracts("06")
Tracts_Sp <- rbind(State_01_Tracts_Sp ,State_02_Tracts_Sp, State_04_Tracts_Sp,
State_05_Tracts_Sp , State_06_Tracts_Sp )
#Decode fips into descriptive state and county names
Tracts_Sp#data$State <-
fips_codes$state_name[match(Tracts_Sp#data$STATEFP,fips_codes$state_code)]
Tracts_Sp#data$County <-
fips_codes$county[match(Tracts_Sp#data$COUNTYFP,fips_codes$county_code)]
#Create a copy of the spatial data's data frame
Data.. <- Tracts_Sp#data
#Set up User Interface
ui <- fluidPage(
titlePanel("Census Viewer Test"),
tabsetPanel(
#Daily Counts Panel
##############
#Hourly Counts Panel
#######################
tabPanel("Tab 1",
#Call plot
fluidRow(column(width = 12,plotlyOutput("county_plot" ))),
#Location Details
fluidRow(
column(3,
h4("Select Details"),
uiOutput("State_selector"),
uiOutput("County_selector"),
uiOutput("Tract_selector")),
column(6,
#h4("Selected Location"),
leafletOutput("map_plot",height = 500))
#Close row
)
#Close panel
)
#Close setPanel
)
#PAge end
)
#Set up Server
#---------------------------
server <- shinyServer(function(session,input,output){
#Temporal Details
##################
#State
output$State_selector <- renderUI({
selectInput(inputId = "State",
label = "State", multiple = FALSE,
choices = c( unique(Data..$State)),
selected = unique(Data..$State)[1])
})
#County selection----
output$County_selector <- renderUI({
available0 <- as.character(unique(Data..$County[Data..$State %in% input$State ]
))
pickerInput(inputId = "County", label = "Select/deselect all + format selected",
choices = as.character(unique(available0)),
options = list(`actions-box` = TRUE, size = 10,`selected-text-format`
= "count > 3"), multiple = TRUE,selected = as.character(unique(available0)))
})
#Tract selection----
output$Tract_selector <- renderUI({
available1 <- as.character(unique(Data..$GEOID[Data..$State %in% input$State ] ))
pickerInput(inputId = "Tract", label = "Select/deselect all + format selected",
choices = as.character(unique(available1)),
options = list(`actions-box` = TRUE, size = 10,`selected-text-format`
= "count > 3"), multiple = TRUE,selected = as.character(unique(available1)))
})
#Graphics
#Select final data and chart-----
output$county_plot <- renderPlotly({
#Select data
dat <- Data..[Data..$State%in%input$State & Data..$County%in%input$County &
Data..$GEOID%in%input$Tract ,]
#Set up axis parameters depending on amount of data
angle = 90
#Initialze chart
ggplotly(ggplot(data = dat, x=GEOID, y = ALAND, fill = State) +
geom_bar(aes(x=GEOID, y = ALAND, fill = State),color = "black",
position = "dodge", stat = "identity")+
ggtitle(paste("Land Area of Select Counties
",unique(dat$State),sep="")) +
#Center plot
theme(plot.title = element_text(hjust = 0.5)) +
ylab("LAnd Area") +
xlab("") +
guides(color=guide_legend("State")) +
theme(axis.text.x = element_text(angle = angle, hjust =
1),plot.background = element_rect(fill = "darkseagreen"))) %>% layout(dragmode =
"select")
})
#Select final data and map-----
output$map_plot <- renderLeaflet({
#Select data
Map_Data_Sp <- Tracts_Sp[Tracts_Sp#data$State%in%input$State,]
class(Map_Data_Sp )
#Create map
Map <- mapview(Map_Data_Sp, map.types = "OpenStreetMap", legend = FALSE,
col.regions = "red",color = "black",cex = 10)
Map#map
#Close map
})
})
#Run App
shinyApp(ui,server)

How to pass a plot (renderPlot) from shiny app as parameter to R Markdown?

I'm trying to download report form shiny app using R Markdown, but I'm lost! I need to pass a plot from shiny as parameter to R Markdown, and then, include this plot in my report.
I searched a lot about this, but I couldn't find anything. How can I plot this in my report?
Server.R
lm_dif_filter <- reactive({
lm_dif_corn[(lm_dif_corn$farmer == input$farmer) & (lm_dif_corn$Treat_X == 'Farmer'),]
})
output$difPlot <- renderPlotly({
dif <- ggplot(data=lm_dif_filter(), aes(x=Treat_Y, y=dif)) +
geom_bar(stat="identity",color = 'black', position=position_dodge(), width = 0.7)+
geom_hline(yintercept = 0) +
#annotate("text", min(Treat_Y), 0, vjust = -1, label = "Farmer")+
theme(legend.position = "none") +
labs(x = "Treats", y = "Diff")
ggplotly(dif)
To download:
output$report <- downloadHandler(
filename = "report.pdf",
content = function(file) {
tempReport <- file.path(tempdir(), "report.Rmd")
file.copy("report.Rmd", tempReport, overwrite = TRUE)
# Set up parameters to pass to Rmd document
params <- list(set_subtitle = input$farmer, plot = output$difPlot)
rmarkdown::render(tempReport, output_file = file,
params = params,
envir = new.env(parent = globalenv())
)
}
)
My report.rmd
---
title: "Some title"
params:
set_subtitle: test
plot: NA
subtitle: "`r params$set_subtitle`"
date: '`r format(Sys.Date(), "%B %d, %Y")`'
output:
pdf_document:
toc: yes
header-includes:
- \usepackage{fancyhdr}
always_allow_html: yes
---
\addtolength{\headheight}{1.0cm}
\pagestyle{fancyplain}
\lhead{\includegraphics[height=1.2cm]{bg.png}}
\renewcommand{\headrulewidth}{0pt}
```{r, include=FALSE}
options(tinytex.verbose = TRUE)
knitr::opts_chunk$set(echo = FALSE)
cat(params$plot)
One easy option is to not pass the plot, and instead pass the parameter, and refer to a shared plot function used by the shiny app and Rmd doc. For example,
Shiny app,
note the source("util.R") and report_hist(params$n)
source("util.R")
library(shiny)
shinyApp(
ui = fluidPage(
sliderInput("slider", "Slider", 1, 100, 50),
downloadButton("report", "Generate report"),
plotOutput("report_hist")
),
server = function(input, output) {
output$report_hist <- renderPlot({
report_hist(n = input$slider)
})
output$report <- downloadHandler(
# For PDF output, change this to "report.pdf"
filename = "report.html",
content = function(file) {
# Copy the report file to a temporary directory before processing it, in
# case we don't have write permissions to the current working dir (which
# can happen when deployed).
tempReport <- file.path(tempdir(), "report.Rmd")
file.copy("report.Rmd", tempReport, overwrite = TRUE)
# Set up parameters to pass to Rmd document
params <- list(n = input$slider)
# Knit the document, passing in the `params` list, and eval it in a
# child of the global environment (this isolates the code in the document
# from the code in this app).
rmarkdown::render(tempReport, output_file = file,
params = params,
envir = new.env(parent = globalenv())
)
}
)
}
)
Rmd report,
note the report_hist(params$n)
---
title: "Dynamic report"
output: html_document
params:
n: NA
---
```{r}
# The `params` object is available in the document.
params$n
```
A plot of `params$n` random points.
```{r}
report_hist(params$n) #note this function was created in util.R and loaded by the shiny app.
```
Shared function in util.R
report_hist <- function(n){
hist(rnorm(n))
}
Here's a demo shiny app you can test it out with, https://rstudio.cloud/project/295626

Creating multiple numeric input according to the variables of an uploaded dataset

I am working on a Shiny app that allows the user to upload their own data and analyze them. At a certain point, I'd like to allow the user to introduce new data as numeric input and to build a new table including them.
I'd like my app to do it dynamically, i.e. creating a box in the sidebar panel containing new numeric input accordingly and with the name of the variables of my uploaded dataset.
I can do it by indicating a priori specific variables, but I'd like to make it dynamic.
I'd be really glad if somebody could attend to this matter.
Here's included a simple example of my code and a screenshot showing how it looks like (but with a priori specified variables).
library(shiny)
ui <- fluidPage(
tabPanel("New Cases", icon=icon("edit"),
sidebarLayout(
sidebarPanel(width=3, #sidebarPanel "New Cases"
conditionalPanel(
'input.dataset02 === "Edit Table"',
textInput('NewID', HTML('<h5><b>Enter Name</b></h5>')), #Enter Factor?
numericInput('NewVal1', HTML('<h5><b>Enter Item</b></h5>'), NULL),
br(),
fluidRow(
column(2, HTML('<h5><b>E14</b></h5>')),
column(4, numericInput("NewVal3", label = NULL, value = NULL)),
column(2, HTML('<h5><b>E16</b></h5>')),
column(4, numericInput("NewVal4", label = NULL, value = NULL))
),
fluidRow(
column(2, HTML('<h5><b>E18_1</b></h5>')),
column(4, numericInput("NewVal5", label = NULL, value = NULL)),
column(2, HTML('<h5><b>E18</b></h5>')),
column(4, numericInput("NewVal6", label = NULL, value = NULL))
),
fluidRow(
column(2, HTML('<h5><b>FAEE</b></h5>')),
column(4, numericInput("NewVal7", label = NULL, value = NULL)),
column(2, HTML('<h5><b>EtG</b></h5>')),
column(4, numericInput("NewVal8", label = NULL, value = NULL))
),
br(),
actionButton("goButton", "Update Table",icon("cloud-upload"),
style="width: 100%; height: 60px; color: steelblue; background-color: #337ab7; border-color: #2e6da4"),
br()
)),
mainPanel(
tabsetPanel(
id = 'dataset02',
tabPanel("Edit Table",
br(),
dataTableOutput("table3"))
))
)))
server <- function(input, output) {
mydata3 = data.frame(Name=letters[NULL], Item=sample(NULL),Piece=sample(NULL), E14=sample(NULL), E16=sample(NULL),
E18_1=sample(NULL), E18=sample(NULL), FAEE=sample(NULL), ETG=sample(NULL))
output$table3 <- renderDataTable( df3())
df3 <- eventReactive(input$goButton, {
if(input$NewID!=" " && !is.null(input$NewVal1)
&& !is.null(input$NewVal3) && !is.null(input$NewVal4) && !is.null(input$NewVal5)
&& !is.null(input$NewVal6) && !is.null(input$NewVal7) && !is.null(input$NewVal8)
&& input$goButton>0)
{
newrow = data.frame(
Name = input$NewID,
Item = input$NewVal1,
Piece = 1,
E14 = input$NewVal3,
E16 = input$NewVal4,
E18_1 = input$NewVal5,
E18 = input$NewVal6,
FAEE = input$NewVal7,
ETG = input$NewVal8)
mydata3 <<- rbind(mydata3, newrow)
}
mydata3
}, ignoreNULL = FALSE)
}
shinyApp(ui = ui, server = server)
Screenshot of the app (in the "desired" format) is the following:
You can create inputs dynamically with renderUI and uiOutput.
Example:
# LIBRARIES & SOURCING --------------
library(shiny)
library(shinydashboard)
# UI -----------------
ui <- dashboardPage(title="App Title",
dashboardHeader(disable = TRUE),
dashboardSidebar(disable = TRUE),
dashboardBody(
fluidRow(
uiOutput("uiOut1")
)
))
# SERVER -----------------
server <- function(input, output) {
output$uiOut1 = renderUI(
list(
numericInput("dynInput1", "First dynamic input:", 20, 0, 40),
numericInput("dynInput2", "Second dynamic input:", 20, 0, 40)
)
)
}
shinyApp(ui = ui, server = server)
You can then refer to the inputs with input$dynInput1 or input[["dynInput1"]] if you need to use a variable to select which input you want.
More info here: https://shiny.rstudio.com/articles/dynamic-ui.html

shinyApp with mysql database

shinyApp code is attached. I'm using data from mysql database and want to display data table based on the query and str and summary of the data. Code is running properly. Do I need to connect to database again and again to get displays of str, summary and table in my shiny app?
library(shiny)
library(DBI)
library(RMySQL)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("dataset", "Choose a dataset:",
choices = c("city", "country","countrylanguage")),
numericInput("obs", "Number of observations to view:", 10),
submitButton("Update View")
),
mainPanel(
tabsetPanel(tabPanel("Table",tableOutput("view")),
tabPanel("Str",verbatimTextOutput("dump")),
tabPanel("Summary",verbatimTextOutput("stats"))
))
)
)
# Define server logic required to summarize and view the
# selected dataset
server<-function(input, output) {
output$view <- renderTable({
conn <- dbConnect(drv = RMySQL::MySQL(),dbname = "world",host = "localhost",username = "root",password = "xxxx")
on.exit(dbDisconnect(conn), add = TRUE)
head(dbReadTable(conn = conn, name = input$dataset), n = input$obs)
})
output$dump <- renderPrint({
conn <- dbConnect(drv = RMySQL::MySQL(),dbname = "world",host = "localhost",username = "root",password = "xxxx")
on.exit(dbDisconnect(conn), add = TRUE)
str(dbReadTable(conn = conn, name = input$dataset))
})
output$stats <-renderPrint({
conn <- dbConnect(drv = RMySQL::MySQL(),dbname = "world",host = "localhost",username = "root",password = "xxxx")
on.exit(dbDisconnect(conn), add = TRUE)
summary(dbReadTable(conn = conn, name = input$dataset), n = input$obs)
})
# Return the requested dataset
datasetInput <- reactive({
switch(input$dataset
)})
}
shinyApp(ui, server)