Switch plots based on radio buttons in R shiny conditionalPanel - radio-button

I am trying to create a shiny app with ggvis plots and radio buttons. I have three plots created by ggvis. Users can switch the different plot based on which radio option they select.
For example, if user selects A, only plot1 is displayed on user interface. If user select B, the plot switch to plot2.
My problem is I don't know how to connect the plots with radio buttons. I've been struggling for hours. Thanks a lot for your help!
I have some example code below.
df <- data.frame(Student = c("a","a","a","a","a","b","b","b","b","b","c","c","c","c"),
year = c(seq(2001,2005,1),seq(2003,2007,1),seq(2002,2005,1)),
col1 = runif(14,min = 50,max = 100),
col2 = runif(14,min = 120,max = 200),
col3 = runif(14,min = 60,max = 200),stringsAsFactors=F)
code:
ui = (fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("stu","Choose Student",
choice = unique(df$Student)),
radioButtons("col","Switch Plot",
choices = c("A", "B","C"),
selected = "A")
),
mainPanel(ggvisOutput("plot1")
))
))
server = function(input,output,session){
dataInput = reactive({
gg = df[which(df$Student == input$stu),]
})
vis1 = reactive({
data = dataInput()
data %>%
ggvis(x = ~year, y = ~col1) %>%
layer_points()
})
vis2 = reactive({
data = dataInput()
data %>%
ggvis(x = ~year, y = ~col2) %>%
layer_lines()
})
vis3 = reactive({
data = dataInput()
data %>%
ggvis(x = ~year, y = ~col3) %>%
layer_bars()
})
vis1 %>% bind_shiny("plot1")
vis2 %>% bind_shiny("plot2")
vis3 %>% bind_shiny("plot3")
}
runApp(list(ui = ui, server = server))

As #aosmith say, conditionalPanel works!
library(shiny)
library(ggvis)
df <- data.frame(Student = c("a","a","a","a","a","b","b","b","b","b","c","c","c","c"),
year = c(seq(2001,2005,1),seq(2003,2007,1),seq(2002,2005,1)),
col1 = runif(14,min = 50,max = 100),
col2 = runif(14,min = 120,max = 200),
col3 = runif(14,min = 60,max = 200),stringsAsFactors=F)
ui = (fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("stu","Choose Student",
choice = unique(df$Student)),
radioButtons("col","Switch Plot",
choices = c("A", "B","C"),
selected = "A")
),
mainPanel(
conditionalPanel(
condition = "input.col == 'A'", ggvisOutput("plot1")),
conditionalPanel(
condition = "input.col == 'B'", ggvisOutput("plot2")),
conditionalPanel(
condition = "input.col == 'C'", ggvisOutput("plot3"))
)
)
))
server = function(input,output,session){
dataInput = reactive({
gg = df[which(df$Student == input$stu),]
})
vis1 = reactive({
data = dataInput()
data %>%
ggvis(x = ~year, y = ~col1) %>%
layer_points()
})
vis2 = reactive({
data = dataInput()
data %>%
ggvis(x = ~year, y = ~col2) %>%
layer_lines()
})
vis3 = reactive({
data = dataInput()
data %>%
ggvis(x = ~year, y = ~col3) %>%
layer_bars()
})
vis1 %>% bind_shiny("plot1")
vis2 %>% bind_shiny("plot2")
vis3 %>% bind_shiny("plot3")
}
runApp(list(ui = ui, server = server))

Related

ggplot2_ combining line and barplot in one graph

Let's say I'm creating the grouped barplot by something like this:
data <- data.frame(time = factor(1:3), type = LETTERS[1:4], values = runif(24)*10)
ggplot(data, aes(x = type, y = values, fill = time)) +
stat_summary(fun=mean, geom='bar', width=0.55, size = 1, position=position_dodge(0.75))
Inside each type I want to connect all bar tops (meaning to connect 3 bars for A, 3 bars for B, and so on) with the line.
I'd like to get something like that as a result:
Is there a way to do that ?
Thank you!
I changed the code to another logic that I prefer, that is to prepare the data before using ggplot().
Code
library(dplyr)
library(ggplot2)
data <- data.frame(time = factor(1:3), type = LETTERS[1:4], values = runif(24)*10)
pdata <- data %>% group_by(type,time) %>% summarise(values = mean(values,na.rm = TRUE)) %>% ungroup()
pdata %>%
ggplot(aes(x = type, y = values)) +
geom_col(
mapping = aes(fill = time, group = time),
width = 0.55,
size = 1,
position = position_dodge(0.75)
)+
geom_line(
mapping = aes(group = type),
size = 1,
position = position_dodge2(.75)
)
Output

How to delete NA from the graph

I'm still learning R and I'm not sure why there is NA data in my graph. Considering that I have used the table function to check the variables in the column.
graph
Any suggestions to remove the NA variable in my graph?
Please find below sample of code(not actual dataset):
*Install and load relevant packages
install.packages("tidyverse")
install.packages("lubridate")
install.packages("ggplot2")
install.packages("tibble")
library(tidyverse)
library(lubridate)
library(ggplot2)
library(tibble)
library(dplyr)
*data frame
all_trips <- tribble(~start, ~end, ~start_name, ~type,
"2020-03-22 03:20:20", "2020-03-22 04:10:15", "A", "member",
"2020-03-25 01:01:07", "2020-03-25 05:09:45", NA, "member",
"2020-03-26 07:09:55", "2020-03-26 08:10:20", "B", "casual",
"2020-03-29 09:10:30", "2020-03-29 09:00:20", "A", "casual",
"2020-03-30 11:09:18", "2020-03-30 03:40:10", "B", "member")
*generate new columns
all_trips$date <- as.Date(all_trips$start) #The default format is yyyy-mm-dd
all_trips$month <- format(as.Date(all_trips$date), "%m")
all_trips$day <- format(as.Date(all_trips$date), "%d")
all_trips$year <- format(as.Date(all_trips$date), "%Y")
all_trips$day_of_week <- format(as.Date(all_trips$date), "%A")
all_trips$ride_length <- difftime(all_trips$end,all_trips$start)
is.factor(all_trips$ride_length)
all_trips$ride_length <- as.numeric(as.character(all_trips$ride_length))
is.numeric(all_trips$ride_length)
*data cleaning
all_trips_v2 <- all_trips[!(all_trips$start_name == "NA" |
all_trips$ride_length<0),]
*data viz
all_trips_v2 %>%
mutate(weekday = wday(start, label = TRUE)) %>% #creates weekday field using wday()
group_by(type, weekday) %>% #groups by usertype and weekday
summarise(number_of_rides = n() #calculates the number of rides and average duration
,average_duration = mean(ride_length)) %>% # calculates the average duration
arrange(type, weekday) %>% # sorts
ggplot(aes(x = weekday, y = number_of_rides, fill = type)) +
geom_col(position = "dodge", na.rm = TRUE) +
scale_x_discrete(na.translate = FALSE)
Bar Chart:
Click here
Adding na.rmand na.translate arguments will remove missing values from bar chart without a warning message as shown here:
tibble(x = rep(c('One', 'Two', 'Two', NA),2), Group=rep(c("A","B"),each=4)) %>%
ggplot(aes(x, fill=Group)) +
labs(title="Sample Group Bar Chart with NA's Removed") +
geom_bar(stat="Count", position=position_dodge(), na.rm = TRUE) +
scale_x_discrete(na.translate = FALSE)

Leaflet create separate layer groups

I am creating a leaflet map with two different types of layers:
A layer for total rental households, and a layer for total borrowing households. This layer should be mutually exclusive: i.e., you should only be able to select one of these layers at a time (either show total rental households OR total borrowing households). This will effectively function as a base layer: you can only choose one.
A layer Sydney, and a layer for the Rest of NSW. This layer does not need to be mutually exclusive: i.e., can show both Sydney AND Rest of NSW at the same time. These will effectively function like overlays: you can choose as many as you like.
Currently, I have only figured out how to show these layers as four separate layers: Sydney Renters, Rest of NSW renters, Sydney Borrowers, Rest of NSW Borrowers. (see image)
I would like to have these as two separate layers, with a choice for Renters OR Borrowers, and a separate layer for Sydney AND/OR Rest of NSW.
Here is the code used to generate the map:
leaflet() %>%
addProviderTiles(providers$CartoDB.Positron, group = "OSM (default)") %>%
addPolygons(data = sf_syd, fillColor = ~pal2(Renting), color="white", weight=1, fillOpacity=0.4, group="Sydney Renters",
highlight = highlightOptions(weight=2, color="black", fillOpacity = 0.7, bringToFront = TRUE)) %>%
addPolygons(data = sf_nsw, fillColor = ~pal2(Renting), color="white", weight=1, fillOpacity=0.4, group="Rest of NSW Renters",
highlight = highlightOptions(weight=2, color="black", fillOpacity = 0.7, bringToFront = TRUE)) %>%
addPolygons(data = sf_syd, fillColor = ~pal2(Borrowing), color="white", weight=1, fillOpacity=0.4, group="Sydney Borrowers",
highlight = highlightOptions(weight=2, color="black", fillOpacity = 0.7, bringToFront = TRUE)) %>%
addPolygons(data = sf_nsw, fillColor = ~pal2(Borrowing), color="white", weight=1, fillOpacity=0.4, group="Rest of NSW Borrowers",
highlight = highlightOptions(weight=2, color="black", fillOpacity = 0.7, bringToFront = TRUE)) %>%
addLayersControl(baseGroups = c("OSM (default)"),
overlayGroups = c("Sydney Renters",
"Rest of NSW Renters",
"Sydney Borrowers",
"Rest of NSW Borrowers"),
options = layersControlOptions(collapsed = FALSE)) %>%
addLegend(data= sf_syd, pal = pal2, values = ~perc_rental_stress, opacity = 0.7, position = "bottomright", title = "Households of </br> Household Type 'X'")
What you want is a user interface to filter the data before it goes into leaflet. This is not possible in Rleaflet without a UI layer like shiny.
You can theoretically create a matrix of combinations and create a layergroup for each possibility but this will not look good when mapping.
A proper shiny based solution looks like this,
library(shiny)
library(leaflet)
library(tmap)
data(World)
ui <- fluidPage(
leafletOutput("mymap"),
p(),
br(),
checkboxInput("asia", label = "Asia", TRUE),
checkboxInput("africa", label = "Africa", TRUE),
radioButtons("value",choiceValues = c("life_exp","footprint"), choiceNames =c("life_exp","footprint"), label = "test", selected = "life_exp")
)
server <- function(input, output, session) {
filtered_world <- reactive({
temp <- World %>% filter(1==2)
if(input$asia) { temp <- rbind(temp, World %>% filter(continent == 'Asia')) }
if(input$africa) { temp <- rbind(temp, World %>% filter(continent == 'Africa')) }
temp$value <- temp[[input$value]]
temp
})
output$mymap <- renderLeaflet({
data <- filtered_world()
pal <- colorNumeric(palette = "Blues",domain = data$value)
leaflet() %>%
addProviderTiles(providers$CartoDB.PositronNoLabels) %>%
addPolygons(data = data, fillColor = ~pal(value),
fillOpacity = 1, color = "black", weight = 1)
})
}
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)

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)