Recently we wanted to visualise some coordinates which are tracked during a specific API call. The goal was helping us to find out if the functionality is used at all and especially where it is used. It might not be a good use of your time to improve a service in Antartica if no one there is trying to use it. Don’t worry, there is no connection between the user and the location.
Wouldn’t it be cool to view that data quickly via heat map?
Remembering R, an environment for statistical computing and graphics, from a past project, we quickly had enough keywords to google for.
A good starting point, although with a sad topic, can be found here. Let’s find a dataset for the following example.
Finding sample data to work with
Your actual data might be located in some database. Feel free to use is as the input. But for the sake of having some unrelated data for this post I’m taking all locations of McDonald’s in Germany. No affiliation whatsoever to the company 😉. These locations can be found using their german restaurant finder. Simply increase the radius of the search area.
curl -X POST http://www.mcdonalds.de/search\?longitude\=9.481544\&latitude\=51.312801\&radius\=1000 > response.json
The location is the coordinates of Kassel, which is close to the center of Germany. A radius of 1000km covers the whole country.
We transform the
reponse.json into CSV via
< response.json | jq '.restaurantList.restaurant | [.latitude,.longitude] | @csv' | tr -d '"' > locations.csv
We will work on the file
locations.csv. We provide some headers for the columns adding the first line
The first four lines of the CSV thus look like
Now we need to put these coordinates on a map. Since Google maps started to require an API key recently why not try out another provider?
In the example we are using stamen, which offers map visualisations using OpenStreetMap data. No API required. Yet.
Setup instructions can be found on GitHub. We start with some dependencies of R.
First we read the contents of our
coords.data <- read.csv(file="./locations.csv")
Then we define the bounds of the to be mapped country. Germany in our case.
map_bounds <- c(left = 5, bottom = 47, right = 16, top = 56)
We configure the map, bounds, zoom and style, via
coords.map <- get_stamenmap(map_bounds, zoom = 7, maptype = "toner-lite")
To next adding the logic for rendering the heat map
coords.map <- ggmap(coords.map, extent="device", legend="none")coords.map <- coords.map + stat_density2d(data=coords.data, aes(x=Longitude, y=Latitude, fill=..level.., alpha=..level..), geom="polygon")coords.map <- coords.map + scale_fill_gradientn(colours=rev(brewer.pal(7, "Spectral")))
And get the output as an image
coords.map <- coords.map + theme_bw()ggsave(filename="./coords.png")
Now we invoke the script via
Rscript script.R and are presented with the following
Nice. Let’s add the actual locations to the map to see how these heat spots were created. Add the next snipped before creating the output via
coords.map <- coords.map + geom_point(data=coords.data, aes(x=Longitude, y=Latitude), fill="red", shape=23, alpha=0.8)
Running the script again yields
Of course, for a company like McDonald’s, this closely resembles the population centers in Germany. But if you are creating an App which is offering surf spots or hiking trails the map might look quite different.
The code with some setup instruction can be found on GitHub