rshinyflexdashboardr-leafletr-highcharter

Flexdashboards and Leaflet and marker click with Highcharts


I am attempting to create a flexdashboard that uses an event (map_marker_click) in Leaflet to show a highcharts column chart in another chart on the same page. I have taken from other examples and cannot find quite what I am looking for in the Flexdashboards tutorials or examples. This is very close to what I am wanting without the shiny inputs or plot.ly integration and using markers instead of polygons (much less going on).

I have the following code for a flexdashboard in R:

title: "Flexdashboards and Leaflet"
output: 
flexdashboard::flex_dashboard:
vertical_layout: fill
runtime: shiny
---

```{r,include=FALSE}
library(flexdashboard)
library(shiny)
library(leaflet)
library(highcharter)
```

```{r,include=FALSE}
latitude<-c(35.94077, 35.83770, 35.84545, 35.81584, 35.79387, 36.05600)
longitude<-c(-78.58010, -78.78084, -78.72444, -78.62568, -78.64262,-78.67600)
amounts1<-c(27, 44, 34, 46, 25, 15)
amounts2<-c(34, 52, 35, 78, 14, 24)
ids<-c("a", "b", "c", "d", "e", "f")
df<-data.frame(ids,amounts1,amounts2,latitude,longitude)
renderLeaflet({ 
leaflet() %>%
addTiles() %>%
addMarkers(lng=c(longitude),lat=c(latitude))
}) 

observeEvent(input$map_marker_click,{
      click<-input$map_marker_click
      if(is.null(click))
        return()
}) 
```

```{r}
renderHighchart({
highchart() %>%
hc_chart(type = 'column')%>%
hc_add_series(name=amounts1, data=click())
hc_add_series(name=amounts2, data=click())
})
```

I am wondering if this could be accomplished in a flexdashboard with or without shiny integration.


Solution

  • The following code will get it done. In brief, the key steps are:

    1. When initializing the map, be sure to specify a column as its layerId. This way Leaflet will know which values to return when you specify an event.
    2. Create an eventReactive that returns the value of that layerId. You can then use this to subset your data as needed to pass to the chart.
    3. I like to create a reactive data frame that is the subset of the master data frame based on the clicked layerId. You could write the app without doing this but I like to separate my Shiny apps out into components as much as I can.
    4. You can now use this reactive data frame - and its values - in your call to renderHighchart

    Hope this helps!

    ---
    title: "Flex Dashboard"
    output: 
      flexdashboard::flex_dashboard:
        orientation: columns
        vertical_layout: fill
    runtime: shiny
    ---
    
    ```{r setup, include=FALSE}
    library(flexdashboard)
    library(shiny)
    library(leaflet)
    library(highcharter)
    
    latitude<-c(35.94077, 35.83770, 35.84545, 35.81584, 35.79387, 36.05600)
    longitude<-c(-78.58010, -78.78084, -78.72444, -78.62568, -78.64262,-78.67600)
    amounts1<-c(27, 44, 34, 46, 25, 15)
    amounts2<-c(34, 52, 35, 78, 14, 24)
    ids<-c("a", "b", "c", "d", "e", "f")
    df<-data.frame(ids,amounts1,amounts2,latitude,longitude)
    ```
    
    Column {data-width=650}
    -----------------------------------------------------------------------
    
    ```{r}
    output$map <- renderLeaflet({
    
      leaflet() %>%
        addTiles() %>%
        addMarkers(data = df, lng = longitude, lat = latitude, 
                   layerId = ~ids)
    
    })
    
    leafletOutput('map')  
    
    ```
    
    Column {data-width=350}
    -----------------------------------------------------------------------
    
    ```{r}
    
    click_marker <- eventReactive(input$map_marker_click, {
    
      x <- input$map_marker_click
    
      return(x$id)
    
    })
    
    data_for_chart <- reactive({
    
      return(df[df$ids == click_marker(), ])
    
    })
    
    output$chart <- renderHighchart({
    
      highchart() %>%
        hc_chart(type = 'column') %>%
        hc_add_series(data = c(data_for_chart()$amounts1, 
                               data_for_chart()$amounts2))
    
    })
    
    highchartOutput('chart')
    
    ```