0
votes

This is not, strictly speaking, a question about Javascript, but I believe that it is the root of the issue. I have a dataset of crime data in Seattle

   Offense       Date Longitude Latitude
3  Assault 2015-10-02 -122.3809 47.66796
5  Assault 2015-10-03 -122.3269 47.63436
6  Assault 2015-10-04 -122.3342 47.57665
7   Weapon 2015-04-12 -122.2984 47.71930
8  Assault 2015-06-30 -122.3044 47.60616
9 Burglary 2015-09-04 -122.2754 47.55392

and I'm trying to make a heatmap in Shiny with rCharts, similar to Ramnath's Houston crime data heatmap demo, which will take a user selected date range and subset of offenses, and draw a heatmap over a Leaflet map.

I have the following ui.R:

library(shiny)
library(rCharts)
library(rjson)

shinyUI(fluidPage(
  headerPanel("Crime in Seattle"), 

  sidebarPanel(
    uiOutput("select.date.ran"), 
    uiOutput("select.crime")
  ), 

  mainPanel(chartOutput("my.map", "leaflet"),
            tags$style('.leaflet {height: 500px;}'),
            tags$head(tags$script(src="leaflet-heat.js")),
            uiOutput('spd.map'))
))

where leaflet-heat.js is in a www folder in the Shiny app directory (I have tried both setting src="http://leaflet.github.io/Leaflet.heat/dist/leaflet-heat.js" and adding a type="text/javascript" in tags$script but I get the same error described below). This is my server.R:

library(shiny)
library(rCharts)
library(rjson)

spd <- readRDS("data/spd.rds")

shinyServer(function(input, output, session) {

  output$select.date.ran <- renderUI({
    dateRangeInput("sel.date", "Choose date range:", 
                   start = "2014/01/01", end = "2015/10/05", 
                   separator = "to", format = "yyyy/mm/dd",
                   startview = "month", weekstart = 0, 
                   language = "en")
  })

  output$select.crime <- renderUI({
    checkboxGroupInput(inputId = "sel.crime", "Select crimes:", 
                  choices = c("Theft", "Fraud", "Drugs/Alcohol", 
                              "Weapon", "Assault", "Disturbance", 
                              "Robbery", "Homicide", "Prostitution"), 
                  selected = "Theft")
  })

  output$my.map <- renderMap({

    my.map <- Leaflet$new() 
      my.map$setView(c(47.5982623,-122.3415519) ,12) 
      my.map$tileLayer(provider="Esri.WorldStreetMap")
    my.map
  })

  output$spd.map <- renderUI({
    spd.dat <- spd[spd$Offense %in% input$sel.crime & 
                       (spd$Date >= input$sel.date[1] &
                          spd$Date <= input$sel.date[2]), c(3, 4)]
    spd.json <- toJSONArray2(spd.dat, json = FALSE, names = FALSE)

    tags$body(tags$script(HTML(sprintf("
                      <script>
                      var addressPoints = %s
                      var heat = L.heatLayer(addressPoints).addTo(map)
                      </script>", rjson::toJSON(spd.json)
              ))))
  })
})

Running the app will show that the map and sidebar elements are displayed properly, but no heatmap appears. If I run it in my browser and check the output of the developer tools Javascript console, I see two "Uncaught SyntaxError: Unexpected token <" errors.

Long story short: what do these errors mean, and how can I resolve them? I believe that the issue boils down to this, but if not, is there some other reason why the heatmap might not be displaying?

Edit: By removing <script> from HTML(sprintf(... the error changes to "Uncaught TypeError: Cannot read property 'lat' of undefined". Is the cause of my first error that <script> should not be there? And is the cause of the new error that L.heatLayer isn't properly reading the json as lat/long coordinates?

1

1 Answers

0
votes

As it turned out, there were two issues, and then a third that arose when the first two were resolved.

Firstly, <script> in HTML(sprintf(... was unnecessary. This is what I think was causing the "Uncaught SyntaxError: Unexpected token <" error.

Once I got that figured out, it seemed that the json wasn't being treated as lat/lon pairs by L.heatLayer. I'm not sure why this worked, but changing

spd.dat <- spd[spd$Offense %in% input$sel.crime & 
                   (spd$Date >= input$sel.date[1] &
                      spd$Date <= input$sel.date[2]), c(3, 4)]
spd.json <- toJSONArray2(spd.dat, json = FALSE, names = FALSE)

to

spd.dat <- spd[spd$Offense %in% input$sel.crime & 
                   (spd$Date >= input$sel.date[1] &
                      spd$Date <= input$sel.date[2]), ]
spd.arr <- toJSONArray2(spd.dat[c(3,4)], json = FALSE, names = FALSE)

i.e., selecting the lat and lon columns inside of tJSONArray2, fixed this.

Finally, once a heatmap showed up, I realized that every change in the state of the map re-drew the heatmap on top of existing ones, to the point where the app would freeze up after a while. This answer provides the solution to this issue.