I was able to create a reactive table from a click event based on the answer provided from the following question, Highcharter - Click event to filter data from graph, however I can't seem to figure out how to add a reactive highchart instead of the table. The code below demonstrates how to make the table.
library (shiny)
library (shinydashboard)
library (dplyr)
library (tibble)
library (highcharter)
library(shinyjs)
library (DT)
rm(list=ls())
header <- dashboardHeader()
sidebar <- dashboardSidebar()
body <- dashboardBody(
fluidRow(
box(
tags$head(tags$style(HTML("#OnTime{height:20vh !important;} "))),
title = "On Time", status = "primary", solidHeader = TRUE, width = 6,
highchartOutput("OnTime")
)
),
fluidRow(
box(
title = "WIP Table", status = "primary", solidHeader = TRUE,
DT::dataTableOutput("Table")
###I know i need to replace this with a highchartOutput
)
),
fluidRow(
box(
textOutput("text")
)
)
)
ui <- dashboardPage(header, sidebar, body)
server <- function(input, output) {
Customer <- c("England", "France", "US", "Canada", "England", "France", "US", "Canada", "England")
OnTime <- c("On Time", "On Time", "Overdue", "On Time", "Overdue", "On Time", "Overdue","On Time", "On Time")
Gate <- c(1,2,3,2,3,2,1,2,3)
Quantity <- c(1,1,1,1,1,1,1,1,1)
data <- data.frame(Customer,OnTime,Gate, Quantity)
output$OnTime <- renderHighchart({
Lvl1GroupingStatus <- aggregate(data$Quantity, by = list(data$OnTime),FUN=sum)
Lvl1dfStatus <- data_frame(name = Lvl1GroupingStatus$Group.1,y = Lvl1GroupingStatus$x,drilldown = tolower(name))
Lvl2WIPOverDue <- data[data$OnTime == "Overdue",]
Lvl2WIPOverDueb <- aggregate(Lvl2WIPOverDue$Quantity, by = list(Lvl2WIPOverDue$Customer),FUN=sum)
Lvl2dfWIPOverDue <- arrange(data_frame(name = Lvl2WIPOverDueb$Group.1,value = Lvl2WIPOverDueb$x),desc(value))
Lvl2WIPOnTime <- data[data$OnTime == "On Time",]
Lvl2WIPOnTimeb <- aggregate(Lvl2WIPOnTime$Quantity, by = list(Lvl2WIPOnTime$Customer),FUN=sum)
Lvl2dfWIPOnTime <- arrange(data_frame(name = Lvl2WIPOnTimeb$Group.1,value = Lvl2WIPOnTimeb$x),desc(value))
ClickFunction <- JS("function(event) {Shiny.onInputChange('Clicked', event.point.name);}")
highchart() %>%
hc_chart(type = "column") %>%
hc_xAxis(type = "category") %>%
hc_legend(enabled = FALSE) %>%
hc_yAxis(gridLineWidth = 0) %>%
hc_plotOptions(series = list(column = list(stacking = "normal"),
borderWidth=0,
dataLabels = list(enabled = TRUE),
events = list(click = ClickFunction)
)
) %>%
hc_add_series(data=Lvl1dfStatus,name="Status", colorByPoint = TRUE,colors = c("#003395","#D20000")) %>%
hc_drilldown(
allowPointDrilldown = TRUE,
series = list(
list(id = "overdue", data = list_parse2(Lvl2dfWIPOverDue), name="Customer"),
list(id = "on time", data = list_parse2(Lvl2dfWIPOnTime), name="Customer")
)
)
})
makeReactiveBinding("outputText")
observeEvent(input$Clicked, {
outputText <<- paste0(input$Clicked)
})
output$text <- renderText({
outputText
})
###Can I use this same filtering format with highchart instead of DT?
output$Table <- DT::renderDataTable({
temp <- data
rowcheck <- temp[temp$OnTime == input$Clicked,]
if (nrow(rowcheck)!=0) {
temp <- temp[temp$OnTime == input$Clicked,]
Lvl1Click <<- input$Clicked
}
else {
temp <- temp[temp$OnTime == Lvl1Click,]
temp <- temp[temp$Customer == input$Clicked,]
}
return (temp)
})
}
#Combines Dasboard and Data together
shinyApp(ui, server)
thanks!
The code below is where i am having issues. Assume I've updated the body to show a second highchart vs a table.
output$chart2<- renderhighchart({
temp <- data
rowcheck <- temp[temp$RESERVOIR == input$Clicked,]
if (nrow(rowcheck)!=0) {
temp <- temp[temp$RESERVOIR == input$Clicked,]
Lvl1Click <<- input$Clicked
}
else {
temp <- temp[temp$RESERVOIR == Lvl1Click,]
temp <- temp[temp$RESERVOIR == input$Clicked,]
}
return (temp)
hchart(**temp**, "scatter", hcaes(x = Customer, y = Quantity))
This does not work. I'm not sure where/how to include the temp dataset in the hchart.
This is the follow up after changing to highchartoutput and renderHighchart.
ui <- dashboardPage(header, sidebar, body)
server <- function(input, output) {
Customer <- c("England", "France", "US", "Canada", "England", "France", "US", "Canada", "England")
OnTime <- c("On Time", "On Time", "Overdue", "On Time", "Overdue", "On Time", "Overdue","On Time", "On Time")
Gate <- c(1,2,3,2,3,2,1,2,3)
Quantity <- c(1,1,1,1,1,1,1,1,1)
data <- data.frame(Customer,OnTime,Gate, Quantity)
output$OnTime <- renderHighchart({
Lvl1GroupingStatus <- aggregate(data$Quantity, by = list(data$OnTime),FUN=sum)
Lvl1dfStatus <- data_frame(name = Lvl1GroupingStatus$Group.1,y = Lvl1GroupingStatus$x,drilldown = tolower(name))
Lvl2WIPOverDue <- data[data$OnTime == "Overdue",]
Lvl2WIPOverDueb <- aggregate(Lvl2WIPOverDue$Quantity, by = list(Lvl2WIPOverDue$Customer),FUN=sum)
Lvl2dfWIPOverDue <- arrange(data_frame(name = Lvl2WIPOverDueb$Group.1,value = Lvl2WIPOverDueb$x),desc(value))
Lvl2WIPOnTime <- data[data$OnTime == "On Time",]
Lvl2WIPOnTimeb <- aggregate(Lvl2WIPOnTime$Quantity, by = list(Lvl2WIPOnTime$Customer),FUN=sum)
Lvl2dfWIPOnTime <- arrange(data_frame(name = Lvl2WIPOnTimeb$Group.1,value = Lvl2WIPOnTimeb$x),desc(value))
ClickFunction <- JS("function(event) {Shiny.onInputChange('Clicked', event.point.name);}")
highchart() %>%
hc_chart(type = "column") %>%
hc_xAxis(type = "category") %>%
hc_legend(enabled = FALSE) %>%
hc_yAxis(gridLineWidth = 0) %>%
hc_plotOptions(series = list(column = list(stacking = "normal"),
borderWidth=0,
dataLabels = list(enabled = TRUE),
events = list(click = ClickFunction)
)
) %>%
hc_add_series(data=Lvl1dfStatus,name="Status", colorByPoint = TRUE,colors = c("#003395","#D20000")) %>%
hc_drilldown(
allowPointDrilldown = TRUE,
series = list(
list(id = "overdue", data = list_parse2(Lvl2dfWIPOverDue), name="Customer"),
list(id = "on time", data = list_parse2(Lvl2dfWIPOnTime), name="Customer")
)
)
})
makeReactiveBinding("outputText")
observeEvent(input$Clicked, {
outputText <<- paste0(input$Clicked)
})
output$text <- renderText({
outputText
})
###Can I use this same filtering format with highchart instead of DT?
output$chart2 <- renderHighchart({
temp <- data
rowcheck <- temp[temp$OnTime == input$Clicked,]
if (nrow(rowcheck)!=0) {
temp <- temp[temp$OnTime == input$Clicked,]
Lvl1Click <<- input$Clicked
}
else {
temp <- temp[temp$OnTime == Lvl1Click,]
temp <- temp[temp$Customer == input$Clicked,]
}
return (temp)
hchart(temp, "scatter", hcaes(x = Customer, y = Quantity))
})
}
#Combines Dasboard and Data together
shinyApp(ui, server)
Running the above code gets shows the image below
Since I cannot post that much into a comment, here is my solution. However, I am not 100% sure whether this is what OP intended
library (shiny)
library (shinydashboard)
library (dplyr)
library (tibble)
library (highcharter)
library(shinyjs)
library (DT)
rm(list=ls())
header <- dashboardHeader()
sidebar <- dashboardSidebar()
body <- dashboardBody(
fluidRow(
box(
tags$head(tags$style(HTML("#OnTime{height:20vh !important;} "))),
title = "On Time", status = "primary", solidHeader = TRUE, width = 6,
highchartOutput("OnTime")
)
),
fluidRow(
box(
title = "WIP Table", status = "primary", solidHeader = TRUE,
highchartOutput("Table")
###I know i need to replace this with a highchartOutput
)
),
fluidRow(
box(
textOutput("text")
)
)
)
ui <- dashboardPage(header, sidebar, body)
server <- function(input, output) {
Customer <- c("England", "France", "US", "Canada", "England", "France", "US", "Canada", "England")
OnTime <- c("On Time", "On Time", "Overdue", "On Time", "Overdue", "On Time", "Overdue","On Time", "On Time")
Gate <- c(1,2,3,2,3,2,1,2,3)
Quantity <- c(1,1,1,1,1,1,1,1,1)
data <- data.frame(Customer,OnTime,Gate, Quantity)
output$OnTime <- renderHighchart({
Lvl1GroupingStatus <- aggregate(data$Quantity, by = list(data$OnTime),FUN=sum)
Lvl1dfStatus <- data_frame(name = Lvl1GroupingStatus$Group.1,y = Lvl1GroupingStatus$x,drilldown = tolower(name))
Lvl2WIPOverDue <- data[data$OnTime == "Overdue",]
Lvl2WIPOverDueb <- aggregate(Lvl2WIPOverDue$Quantity, by = list(Lvl2WIPOverDue$Customer),FUN=sum)
Lvl2dfWIPOverDue <- arrange(data_frame(name = Lvl2WIPOverDueb$Group.1,value = Lvl2WIPOverDueb$x),desc(value))
Lvl2WIPOnTime <- data[data$OnTime == "On Time",]
Lvl2WIPOnTimeb <- aggregate(Lvl2WIPOnTime$Quantity, by = list(Lvl2WIPOnTime$Customer),FUN=sum)
Lvl2dfWIPOnTime <- arrange(data_frame(name = Lvl2WIPOnTimeb$Group.1,value = Lvl2WIPOnTimeb$x),desc(value))
ClickFunction <- JS("function(event) {Shiny.onInputChange('Clicked', event.point.name);}")
highchart() %>%
hc_chart(type = "column") %>%
hc_xAxis(type = "category") %>%
hc_legend(enabled = FALSE) %>%
hc_yAxis(gridLineWidth = 0) %>%
hc_plotOptions(series = list(column = list(stacking = "normal"),
borderWidth=0,
dataLabels = list(enabled = TRUE),
events = list(click = ClickFunction)
)
) %>%
hc_add_series(data=Lvl1dfStatus,name="Status", colorByPoint = TRUE,colors = c("#003395","#D20000")) %>%
hc_drilldown(
allowPointDrilldown = TRUE,
series = list(
list(id = "overdue", data = list_parse2(Lvl2dfWIPOverDue), name="Customer"),
list(id = "on time", data = list_parse2(Lvl2dfWIPOnTime), name="Customer")
)
)
})
makeReactiveBinding("outputText")
observeEvent(input$Clicked, {
outputText <<- paste0(input$Clicked)
})
output$text <- renderText({
outputText
})
###Can I use this same filtering format with highchart instead of DT?
output$Table <- renderHighchart({
temp <- data
rowcheck <- temp[temp$OnTime == input$Clicked,]
if (nrow(rowcheck)!=0) {
temp <- temp[temp$OnTime == input$Clicked,]
Lvl1Click <<- input$Clicked
}
else {
temp <- temp[temp$OnTime == Lvl1Click,]
temp <- temp[temp$Customer == input$Clicked,]
}
hchart(temp, "scatter", hcaes(x = Customer, y = Quantity))
})
}
#Combines Dasboard and Data together
shinyApp(ui, server)
This is my output:
Related
I'm trying to use some reactive elements from predefined function and call that data from a module to generate plots, but data is not getting updated upon selection. I've also tried to call the function inside reactive() and call that from the module, but still same result. My approach is below:
library(shiny)
library(shinyWidgets)
library(highcharter)
library(data.table)
library(dplyr)
employement_type_count <- function(
data,
category,
...
){
data[employee_category %in% category, .(count = .N), by = employee_category]
}
pie_chart_ui <- function(id) {
ns <- NS(id)
highchartOutput(ns("pie"))
}
pie_chart_server <- function(
id,
data,
var_x = names(data)[1],
var_y = names(data)[2],
lab_x = names(data)[1],
lab_y = names(data)[2],
tooltip_name = names(data)[2],
export_title = NA
) {
moduleServer(
id,
function(input, output, session) {
output$pie <- renderHighchart({
data %>%
hchart(
'pie',
hcaes_(x = var_x, y = var_y),
name = tooltip_name
) %>%
hc_xAxis(title = list(text = lab_x)) %>%
hc_yAxis(title = list(text = lab_y)) %>%
hc_plotOptions(
pie = list(
allowPointSelect = TRUE,
cursor = 'pointer',
dataLabels = list(
enabled = TRUE,
format = '<b>{point.name}</b>: {point.percentage:.1f}%',
style = list(
color = "(Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black'"
)
)
)
) %>%
hc_exporting(
enabled = TRUE,
buttons = list(
contextButton = list(
align = 'right'
)
),
chartOptions = list(
title = list(
text = export_title
)
)
)
})
}
)
}
ui <- fluidPage(
sidebarPanel(
pickerInput(
"employee_type",
"Employee Type",
choices = c("Regular", "Project", "Service", "Part-Time"),
selected = c("Regular", "Project", "Service", "Part-Time"),
multiple = TRUE
)
),
mainPanel(
pie_chart_ui("employee_category")
)
)
server <- function(input, output, session){
# data_common <- fread("data_common.csv")
data_common <- data.table(
id = 1:26,
employee_name = LETTERS,
gender_type = rep(c("Male", "Female"), each = 13),
employee_category = c("Regular", "Project", rep(c("Regular", "Project", "Service", "Part-Time"), times = 6))
)
pie_chart_server(
"employee_category",
employement_type_count(
data_common,
input$employee_type
)
)
}
shinyApp(ui, server)
Note that, data should be imported from server, instead of global, as it is constantly getting updated.
One way to do it is shown below.
library(shiny)
library(shinyWidgets)
library(highcharter)
library(data.table)
library(dplyr)
df1 <- data.table(
id = 1:26,
employee_name = LETTERS,
gender_type = rep(c("Male", "Female"), each = 13),
employee_category = c("Regular", "Project", rep(c("Regular", "Project", "Service", "Part-Time"), times = 6))
)
employement_type_count <- function(
data,
category,
...
){
data <- data()
if (is.null(category())) {df <- data
}else df <- data[employee_category %in% category(), .(count = .N), by = employee_category]
return(df)
}
pie_chart_ui <- function(id) {
ns <- NS(id)
highchartOutput(ns("pie"))
}
pie_chart_server <- function(
id,
data,
var_x = names(data)[1],
var_y = names(data)[2],
lab_x = names(data)[1],
lab_y = names(data)[2],
tooltip_name = names(data)[2],
export_title = NA
) {
moduleServer(
id,
function(input, output, session) {
output$pie <- renderHighchart({
data %>%
hchart(
'pie',
hcaes_(x = var_x, y = var_y),
name = tooltip_name
) %>%
hc_xAxis(title = list(text = lab_x)) %>%
hc_yAxis(title = list(text = lab_y)) %>%
hc_plotOptions(
pie = list(
allowPointSelect = TRUE,
cursor = 'pointer',
dataLabels = list(
enabled = TRUE,
format = '<b>{point.name}</b>: {point.percentage:.1f}%',
style = list(
color = "(Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black'"
)
)
)
) %>%
hc_exporting(
enabled = TRUE,
buttons = list(
contextButton = list(
align = 'right'
)
),
chartOptions = list(
title = list(
text = export_title
)
)
)
})
}
)
}
ui <- fluidPage(
sidebarPanel(
pickerInput(
"employee_type",
"Employee Type",
choices = c("Regular", "Project", "Service", "Part-Time"),
selected = c("Regular", "Project", "Service", "Part-Time"),
multiple = TRUE
)
),
mainPanel(
pie_chart_ui("employee_category")
)
)
server <- function(input, output, session){
# data_common <- fread("data_common.csv")
data_common <- reactive(df1)
employee <- reactive(input$employee_type)
observe({
mydata <- employement_type_count(
data_common,
employee
)
pie_chart_server(
"employee_category",
mydata
)
})
}
shinyApp(ui, server)
I would like to be able to select an item in the list by grouped names. Unfortunately, the group does not appear for a single name, as seen in the picture below. How can I change it?
My code:
library(plotly)
library(dplyr)
library(shiny)
library(shinyWidgets)
trend_pal <- c('red','blue', 'yellow', 'green') #Palette
TD <- data.frame(Name = rep(c("John Smith", "Antonio Gilbert", "Rickie Hooley", "John Marquez", "Christian Thompson", "Rickie Galvan", "John Anan", "Antonio Rossi")[1:8], each = 12),
Month = rep(month.abb[1:12],8,replace = TRUE),
Value = sample(c(0:300),96, replace = T), stringsAsFactors = F)
TD=as.tbl(TD)
output <- split(TD[,1], sub("\\s.*", " ", TD$Name))
for (i in seq_along(output)){
colnames(output[[i]]) <- ''
}
# UI
ui <- fluidPage(
pickerInput("All", "Choose", multiple = T,choices = c("Antonio" = unique(output$Antonio), 'Christian' = unique(output$Christian),
"John" = unique(output$John), 'Rickie' = unique(output$Rickie)),
options = list(`max-options` = 4,size = 10)),
plotlyOutput('plot')
)
# Server code
server <- function(input, output) {
output$plot <- renderPlotly({
#Filtering data based on user input
trend <- TD %>%
filter(Name %in% input$All) %>%
arrange(Month) %>%
droplevels()
#Plot
plot_ly(data=trend, x=~Month, y = ~Value,
type = 'scatter', mode = 'lines+markers',
color = ~Name , colors = trend_pal)
})
}
# Return a Shiny app object
shinyApp(ui = ui, server = server)
you can see this example option-groups-for-selectize-input, when you have just one name in your group, you have to set a list. in your case :
ui <- fluidPage(
pickerInput("All", "Choose", multiple = T,choices = c("Antonio" = unique(output$Antonio), 'Christian' = list(unique(output$Christian)),
"John" = unique(output$John), 'Rickie' = unique(output$Rickie)),
options = list(`max-options` = 4,size = 10)),
plotlyOutput('plot')
)
EDIT : to answer your comment
library(plotly)
library(dplyr)
library(shiny)
library(shinyWidgets)
trend_pal <- c('red','blue', 'yellow', 'green') #Palette
TD <- data.frame(Name = rep(c("John Smith", "Antonio Gilbert", "Rickie Hooley", "John Marquez", "Christian Thompson", "Rickie Galvan", "John Anan", "Antonio Rossi")[1:8], each = 12),
Month = rep(month.abb[1:12],8,replace = TRUE),
Value = sample(c(0:300),96, replace = T), stringsAsFactors = F)
output <- split(TD[,1], sub("\\s.*", "", TD$Name))
# creation of choices
choices <- lapply(output,function(x){
if(length(unique(x))>1){
unique(x)
} else{
list(unique(x))
}
})
# UI
ui <- fluidPage(
pickerInput("All", "Choose", multiple = T,choices = choices,
options = list(`max-options` = 4,size = 10)),
plotlyOutput('plot')
)
# Server code
server <- function(input, output) {
output$plot <- renderPlotly({
#Filtering data based on user input
trend <- TD %>%
filter(Name %in% input$All) %>%
arrange(Month) %>%
droplevels()
#Plot
plot_ly(data=trend, x=~Month, y = ~Value,
type = 'scatter', mode = 'lines+markers',
color = ~Name , colors = trend_pal)
})
}
# Return a Shiny app object
shinyApp(ui = ui, server = server)
Using a highchart in R (using the highcharter package) I'm trying to select all the points for a single category when selecting any single point. The code below allows selecting a single slice of a stack in a stacked bar chart. I want the entire stacked bar to be selected/deselected by clicking on any of the stacked bar slices.
library("shiny")
library("highcharter")
ui <- shinyUI(
fluidPage(
column(width = 8, highchartOutput("hcontainer", height = "500px")),
column(width = 4, textOutput("text"))
)
)
server <- function(input, output) {
a <- data.frame(b = LETTERS[1:10], b_alt = LETTERS[11:20], c = 11:20, d = 21:30, e = 31:40)
output$hcontainer <- renderHighchart({
canvasClickFunction <- JS("function(event) {Shiny.onInputChange('canvasClicked', [this.name, event.point.series.chart.series[0].options.additionalInfo[event.point.index]]);}")
legendClickFunction <- JS("function(event) {Shiny.onInputChange('legendClicked', this.name);}")
highchart() %>%
hc_xAxis(categories = a$b) %>%
hc_add_series(name = "c", additionalInfo = a$b_alt, data = a$c, color = "red") %>%
hc_add_series(name = "d", data = a$d) %>%
hc_add_series(name = "e", data = a$e) %>%
hc_plotOptions(series = list(stacking = TRUE, allowPointSelect = TRUE, events = list(click = canvasClickFunction, legendItemClick = legendClickFunction))) %>%
hc_chart(type = "column")
})
makeReactiveBinding("outputText")
observeEvent(input$canvasClicked, {
outputText <<- paste0("You clicked on series ", input$canvasClicked[1], " and the bar you clicked was from category ", input$canvasClicked[2], ".")
})
observeEvent(input$legendClicked, {
outputText <<- paste0("You clicked into the legend and selected series ", input$legendClicked, ".")
})
output$text <- renderText({
outputText
})
}
shinyApp(ui, server)
You can fire the event on point click (let's call that clicked point clickedPoint) loop through all series and then through all points, check if the point has the same category as our clickedPoint and if yes, select it using point.select() method.
Here is the main code:
hc_plotOptions(series = list(stacking = TRUE, events = list(click = canvasClickFunction, legendItemClick = legendClickFunction), point = list(events = list(click = JS(
"function() {
var clickedPoint = this;
clickedPoint.series.chart.series.forEach(function(series) {
series.points.forEach(function(point) {
if (point.category === clickedPoint.category) {
if (point.selected) {
point.select(false, true)
} else {
point.select(true, true)
}
}
})
})
}"
))))) %>%
And here is the whole code:
library("shiny")
library("highcharter")
ui <- shinyUI(
fluidPage(
column(width = 8, highchartOutput("hcontainer", height = "500px")),
column(width = 4, textOutput("text"))
)
)
server <- function(input, output) {
a <- data.frame(b = LETTERS[1:10], b_alt = LETTERS[11:20], c = 11:20, d = 21:30, e = 31:40)
output$hcontainer <- renderHighchart({
canvasClickFunction <- JS("function(event) {Shiny.onInputChange('canvasClicked', [this.name, event.point.series.chart.series[0].options.additionalInfo[event.point.index]]);}")
legendClickFunction <- JS("function(event) {Shiny.onInputChange('legendClicked', this.name);}")
highchart() %>%
hc_xAxis(categories = a$b) %>%
hc_add_series(name = "c", additionalInfo = a$b_alt, data = a$c, color = "red") %>%
hc_add_series(name = "d", data = a$d) %>%
hc_add_series(name = "e", data = a$e) %>%
hc_plotOptions(series = list(stacking = TRUE, events = list(click = canvasClickFunction, legendItemClick = legendClickFunction), point = list(events = list(click = JS(
"function() {
var clickedPoint = this;
clickedPoint.series.chart.series.forEach(function(series) {
series.points.forEach(function(point) {
if (point.category === clickedPoint.category) {
if (point.selected) {
point.select(false, true)
} else {
point.select(true, true)
}
}
})
})
}"
))))) %>%
hc_chart(type = "column")
})
makeReactiveBinding("outputText")
observeEvent(input$canvasClicked, {
outputText <<- paste0("You clicked on series ", input$canvasClicked[1], " and the bar you clicked was from category ", input$canvasClicked[2], ".")
})
observeEvent(input$legendClicked, {
outputText <<- paste0("You clicked into the legend and selected series ", input$legendClicked, ".")
})
output$text <- renderText({
outputText
})
}
shinyApp(ui, server)
API: https://api.highcharts.com/class-reference/Highcharts.Point#select
https://api.highcharts.com/highcharts/plotOptions.column.point.events.click
jsFiddle with a pure JS implementation: https://jsfiddle.net/BlackLabel/p135s4vm/
I have the following Shiny Application:
rm(list=ls())
# requirements
requirement_vector <- c("shiny", "leaflet", "tidyverse", "gtfsr", "dataMeta")
lapply(requirement_vector, require, character.only = TRUE)
# data load
{
zip <- get_feed(url = "https://github.com/septadev/GTFS/releases/download/v201812161/gtfs_public.zip",
paste0(getwd(), "/SEPTA_Site"),
quiet = FALSE)
unzip(zip, exdir = paste0(getwd(), "/SEPTA_Site"))
RailData <- import_gtfs(paste0(getwd(), "/SEPTA_Site/google_rail.zip"), local = TRUE)
BusData <- import_gtfs(paste0(getwd(), "/SEPTA_Site/google_bus.zip"), local = TRUE)
delete_vector <- list.files(paste0(getwd(), "/SEPTA_Site"), pattern = "*.zip*")
lapply(as.list(delete_vector), function(x) file.remove(paste0(getwd(), "/SEPTA_Site/", x, "")))
Lines <- c('Broad Street Line', 'Bus', 'Market Frankford Line', 'Regional Rail', 'Trolley')
RRRouteNames <- unique(RailData[["routes_df"]][["route_short_name"]]) %>% sort()
BRouteNames <- unique(BusData[["routes_df"]][["route_id"]])
rmv <- c('BSL', 'BSO', 'MFL', 'MFO', 'NHSL', 'LUCYGO', 'LUCYGR')
BRouteNames <- BRouteNames[!BRouteNames %in% rmv]
TRouteNames <- c('10', '11', '13', '15', '34', '36', '101', '102')
BRouteNames <- BRouteNames[!BRouteNames %in% TRouteNames]
df <- RailData[["stops_df"]]
df <- df %>% inner_join(RailData[["stop_times_df"]],df , by = "stop_id")
df <- df %>% inner_join(RailData[["trips_df"]],df , by = "trip_id")
df <- df %>% inner_join(RailData[["routes_df"]],df , by = "route_id")
keep_vector <- c("stop_id", "stop_name", "stop_lat", "stop_lon", "zone_id",
"arrival_time", "departure_time", "route_id", "route_text_color",
"direction_id", "route_short_name")
df <- unique(df[keep_vector])
df$route_short_name <- paste("Route ", df$route_short_name)
rm(delete_vector, requirement_vector,keep_vector, rmv, zip)
}
# ui
{
ui <- fluidPage(
# App title
titlePanel("Septa Price Map"),
sidebarLayout(
sidebarPanel(
# Input: Input for type & line
selectInput(inputId = "line", label = "Choose Your Service:",
choices = Lines, selected = "Broad Street Line"),
conditionalPanel(
condition = "input.line == 'Regional Rail'",
selectInput(inputId = "line2", label = "Choose Your Route:",
choices = RRRouteNames)),
conditionalPanel(
condition = "input.line == 'Trolley'",
selectInput(inputId = "line3", label = "Choose Your Route:",
choices = TRouteNames)),
conditionalPanel(
condition = "input.line == 'Bus'",
selectInput(inputId = "line4", label = "Choose Your Route:",
choices = BRouteNames)),
conditionalPanel(
condition = "input.line == 'Bus' || input.line == 'Trolley'",
textOutput(outputId = "description")),
actionButton(inputId = "clear", label = "Clear Selection")
),
mainPanel({
leafletOutput(outputId = "MyMap")
})
)
)
}
# server
{
server <- function(input, output) {
output$MyMap <- renderLeaflet({
if (input$line == "Broad Street Line"){
map_gtfs(gtfs_obj = BusData, route_ids = 'BSL', stop_opacity = .75) %>% addProviderTiles(providers$Stamen.Terrain)
} else if (input$line == "Market Frankford Line"){
map_gtfs(gtfs_obj = BusData, route_ids = 'MFL', stop_opacity = .75) %>% addProviderTiles(providers$Stamen.Terrain)
} else if (input$line == "Trolley"){
map_gtfs(gtfs_obj = BusData, route_ids = input$line3, stop_opacity = .75) %>% addProviderTiles(providers$Stamen.Terrain)
} else if (input$line == "Bus"){
map_gtfs(gtfs_obj = BusData, route_ids = input$line4, stop_opacity = .75) %>% addProviderTiles(providers$Stamen.Terrain)
} else if (input$line == "Regional Rail"){
map_gtfs(gtfs_obj = RailData, route_ids =
plyr::mapvalues(input$line2,
RailData[["routes_df"]][["route_short_name"]],
RailData[["routes_df"]][["route_id"]],
warn_missing = FALSE),
stop_opacity = .75) %>% addProviderTiles(providers$Stamen.Terrain)
}
})
output$description <- renderText({
if (input$line == "Trolley") {
plyr::mapvalues(input$line3,
BusData[["routes_df"]][["route_id"]],
BusData[["routes_df"]][["route_long_name"]],
warn_missing = FALSE)}
else {
plyr::mapvalues(input$line4,
BusData[["routes_df"]][["route_id"]],
BusData[["routes_df"]][["route_long_name"]],
warn_missing = FALSE)
}
})
observeEvent(input$MyMap_marker_click, {
print(input$MyMap_marker_click)
})
}
}
shinyApp(ui = ui, server = server)
This functions fine so far, it reacts to the initial input and is able to map individual routes. My issue comes from the last few lines of code when I print the Marker Click. The group, latitude and longitude of each stop is printed but not the stopID which is what I'm looking for. In addition, something called $.nonce is printed and I haven't had any luck searching for what that number represents. The stopID appears in the popup so I know it's stored somewhere in the map, I'm just not sure where. I'm new to shiny and leaflet and would appreciate any help.
I would like drag points when x is greater than 5.
Can anyone help me on that?
Example:
library("shiny")
library("highcharter")
ui <- shinyUI(
fluidPage(
column(width = 8, highchartOutput("hcontainer", height = "500px")),
column(width = 4, textOutput("text"))
)
)
server <- function(input, output) {
a <- data.frame(b = LETTERS[1:10], c = 11:20, d = 21:30, e = 31:40)
output$hcontainer <- renderHighchart({
canvasClickFunction <- JS("function(event) {Shiny.onInputChange('canvasClicked', [this.name, event.point.category]);}")
legendClickFunction <- JS("function(event) {Shiny.onInputChange('legendClicked', this.name);}")
highchart() %>%
hc_xAxis(categories = a$b) %>%
hc_add_serie(name = "c", data = a$c) %>%
hc_add_serie(name = "d", data = a$d) %>%
hc_add_serie(name = "e", data = a$e) %>%
hc_plotOptions(series = list(stacking = FALSE, events = list(click = canvasClickFunction, legendItemClick = legendClickFunction))) %>%
hc_chart(type = "column")
})
makeReactiveBinding("outputText")
observeEvent(input$canvasClicked, {
outputText <<- paste0("You clicked on series ", input$canvasClicked[1], " and the bar you clicked was from category ", input$canvasClicked[2], ".")
})
observeEvent(input$legendClicked, {
outputText <<- paste0("You clicked into the legend and selected series ", input$legendClicked, ".")
})
output$text <- renderText({
outputText
})
}
shinyApp(ui, server)