Live Earthquake Map with Shiny and Google Map API
[This article was first published on R tutorial for Spatial Statistics, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
In the post Exchange data between R and the Google Maps API using Shiny I presented a very simple way to allow communication between R and javascript using shiny.Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
This is an example of a practical approach for which that same system can be used to create a useful tool to visualize seismic events collected from USGS in the Google Maps API using R to do some basic data preparation. The procedure to complete this experiment is pretty much identical to what I presented in the post mentioned, so I will not bother you will additional details.
The final map looks like this:
and it is accessible from this site: Earthquake
The colours of the markers depends on magnitude and it is set in R. Below 2 the marker is green, between 2 and 4 is yellow, between 4 and 6 is orange and above 6 is red.
I also set R to export other information about the event to the json file that I then use to populate the infowindow of each marker.
The code for creating this map consists of two pieces, an index.html file (which needs to go in a folder names www) and the file server.r, available below:
Server.r
# server.R #Title: Earthquake Visualization in Shiny #Copyright: Fabio Veronesi library(sp) library(rjson) library(RJSONIO) shinyServer(function(input, output) { output$json <- reactive ({ if(length(input$Earth)>0){ if(input$Earth==1){ hour <- read.table("http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_hour.csv", sep = ",", header = T) if(nrow(hour)>0){ lis <- list() for(i in 1:nrow(hour)){ if(hour$mag[i]<=2){icon="http://maps.gstatic.com/mapfiles/ridefinder-images/mm_20_green.png"} else if(hour$mag[i]>2&hour$mag[i]<=4){icon="http://maps.gstatic.com/mapfiles/ridefinder-images/mm_20_yellow.png"} else if(hour$mag[i]>4&hour$mag[i]<=6){icon="http://maps.gstatic.com/mapfiles/ridefinder-images/mm_20_orange.png"} else {icon="http://maps.gstatic.com/mapfiles/ridefinder-images/mm_20_red.png"} Date.hour <- substring(hour$time[i],1,10) Time.hour <- substring(hour$time[i],12,23) lis[[i]] <- list(i,hour$longitude[i],hour$latitude[i],icon,hour$place[i],hour$depth[i],hour$mag[i],Date.hour,Time.hour) } #This code creates the variable test directly in javascript for export the grid in the Google Maps API #I have taken this part from:http://stackoverflow.com/questions/26719334/passing-json-data-to-a-javascript-object-with-shiny paste('<script>test=', RJSONIO::toJSON(lis), ';setAllMap();Cities_Markers();', '</script>') } } else if(input$Earth==4){ month <- read.table("http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.csv", sep = ",", header = T) if(nrow(month)>0){ lis <- list() for(i in 1:nrow(month)){ if(month$mag[i]<=2){icon="http://maps.gstatic.com/mapfiles/ridefinder-images/mm_20_green.png"} else if(month$mag[i]>2&month$mag[i]<=4){icon="http://maps.gstatic.com/mapfiles/ridefinder-images/mm_20_yellow.png"} else if(month$mag[i]>4&month$mag[i]<=6){icon="http://maps.gstatic.com/mapfiles/ridefinder-images/mm_20_orange.png"} else {icon="http://maps.gstatic.com/mapfiles/ridefinder-images/mm_20_red.png"} Date.month <- substring(month$time[i],1,10) Time.month <- substring(month$time[i],12,23) lis[[i]] <- list(i,month$longitude[i],month$latitude[i],icon,month$place[i],month$depth[i],month$mag[i],Date.month,Time.month) } #This code creates the variable test directly in javascript for export the grid in the Google Maps API #I have taken this part from:http://stackoverflow.com/questions/26719334/passing-json-data-to-a-javascript-object-with-shiny paste('<script>test=', RJSONIO::toJSON(lis), ';setAllMap();Cities_Markers();', '</script>') } } else if(input$Earth==3){ week <- read.table("http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.csv", sep = ",", header = T) if(nrow(week)>0){ lis <- list() for(i in 1:nrow(week)){ if(week$mag[i]<=2){icon="http://maps.gstatic.com/mapfiles/ridefinder-images/mm_20_green.png"} else if(week$mag[i]>2&week$mag[i]<=4){icon="http://maps.gstatic.com/mapfiles/ridefinder-images/mm_20_yellow.png"} else if(week$mag[i]>4&week$mag[i]<=6){icon="http://maps.gstatic.com/mapfiles/ridefinder-images/mm_20_orange.png"} else {icon="http://maps.gstatic.com/mapfiles/ridefinder-images/mm_20_red.png"} Date.week <- substring(week$time[i],1,10) Time.week <- substring(week$time[i],12,23) lis[[i]] <- list(i,week$longitude[i],week$latitude[i],icon,week$place[i],week$depth[i],week$mag[i],Date.week,Time.week) } #This code creates the variable test directly in javascript for export the grid in the Google Maps API #I have taken this part from:http://stackoverflow.com/questions/26719334/passing-json-data-to-a-javascript-object-with-shiny paste('<script>test=', RJSONIO::toJSON(lis), ';setAllMap();Cities_Markers();', '</script>') } } else { day <- read.table("http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.csv", sep = ",", header = T) if(nrow(day)>0){ lis <- list() for(i in 1:nrow(day)){ if(day$mag[i]<=2){icon="http://maps.gstatic.com/mapfiles/ridefinder-images/mm_20_green.png"} else if(day$mag[i]>2&day$mag[i]<=4){icon="http://maps.gstatic.com/mapfiles/ridefinder-images/mm_20_yellow.png"} else if(day$mag[i]>4&day$mag[i]<=6){icon="http://maps.gstatic.com/mapfiles/ridefinder-images/mm_20_orange.png"} else {icon="http://maps.gstatic.com/mapfiles/ridefinder-images/mm_20_red.png"} Date.day <- substring(day$time[i],1,10) Time.day <- substring(day$time[i],12,23) lis[[i]] <- list(i,day$longitude[i],day$latitude[i],icon,day$place[i],day$depth[i],day$mag[i],Date.day,Time.day) } #This code creates the variable test directly in javascript for export the grid in the Google Maps API #I have taken this part from:http://stackoverflow.com/questions/26719334/passing-json-data-to-a-javascript-object-with-shiny paste('<script>test=', RJSONIO::toJSON(lis), ';setAllMap();Cities_Markers();', '</script>') } } } }) })
Index.html
<!DOCTYPE html> <html> <head> <title>Earthquake Visualization in Shiny</title> <!--METADATA--> <meta name="author" content="Fabio Veronesi"> <meta name="copyright" content="©Fabio Veronesi"> <meta http-equiv="Content-Language" content="en-gb"> <meta charset="utf-8"/> <style type="text/css"> html { height: 100% } body { height: 100%; margin: 0; padding: 0 } map-canvas { height: 100%; width:100% } .btn { background: #dde6d8; background-image: -webkit-linear-gradient(top, #dde6d8, #859ead); background-image: -moz-linear-gradient(top, #dde6d8, #859ead); background-image: -ms-linear-gradient(top, #dde6d8, #859ead); background-image: -o-linear-gradient(top, #dde6d8, #859ead); background-image: linear-gradient(to bottom, #dde6d8, #859ead); -webkit-border-radius: 7; -moz-border-radius: 7; border-radius: 7px; font-family: Arial; color: #000000; font-size: 20px; padding: 9px 20px 10px 20px; text-decoration: none; } .btn:hover { background: #f29f9f; background-image: -webkit-linear-gradient(top, #f29f9f, #ab1111); background-image: -moz-linear-gradient(top, #f29f9f, #ab1111); background-image: -ms-linear-gradient(top, #f29f9f, #ab1111); background-image: -o-linear-gradient(top, #f29f9f, #ab1111); background-image: linear-gradient(to bottom, #f29f9f, #ab1111); text-decoration: none; } </style> <script type="text/javascript" src="http://google-maps-utility-library-v3.googlecode.com/svn/tags/markerclusterer/1.0/src/markerclusterer.js"></script> <script src="https://maps.googleapis.com/maps/api/js?v=3.exp&signed_in=true&libraries=drawing"></script> <script type="application/shiny-singletons"></script> <script type="application/html-dependencies">json2[2014.02.04];jquery[1.11.0];shiny[0.11.1];ionrangeslider[2.0.2];bootstrap[3.3.1]</script> <script src="shared/json2-min.js"></script> <script src="shared/jquery.min.js"></script> <link href="shared/shiny.css" rel="stylesheet" /> <script src="shared/shiny.min.js"></script> <link href="shared/ionrangeslider/css/normalize.css" rel="stylesheet" /> <link href="shared/ionrangeslider/css/ion.rangeSlider.css" rel="stylesheet" /> <link href="shared/ionrangeslider/css/ion.rangeSlider.skinShiny.css" rel="stylesheet" /> <script src="shared/ionrangeslider/js/ion.rangeSlider.min.js"></script> <link href="shared/bootstrap/css/bootstrap.min.css" rel="stylesheet" /> <script src="shared/bootstrap/js/bootstrap.min.js"></script> <script src="shared/bootstrap/shim/html5shiv.min.js"></script> <script src="shared/bootstrap/shim/respond.min.js"></script> <script type="text/javascript"> var map = null; var Gmarkers = []; function Cities_Markers() { var infowindow = new google.maps.InfoWindow({ maxWidth: 500,maxHeight:500 }); //Loop to add markers to the map based on the JSON exported from R, which is within the variable test for (var i = 0; i < test.length; i++) { var lat = test[i][2] var lng = test[i][1] var marker = new google.maps.Marker({ position: new google.maps.LatLng(lat, lng), title: 'test', map: map, icon:test[i][3] }); //This sets up the infowindow google.maps.event.addListener(marker, 'click', (function(marker, i) { return function() { infowindow.setContent('<div id="content"><p><b>Location</b> = '+ test[i][4]+'<p>'+ '<b>Depth</b> = '+test[i][5]+'Km <p>'+ '<b>Magnitude</b> = '+test[i][6]+ '<p>'+ '<b>Date</b> = '+test[i][7]+'<p>'+ '<b>Time</b> = '+test[i][8]+'</div>'); infowindow.open(map, marker); } })(marker, i)); Gmarkers.push(marker); }; }; //Function to remove all the markers from the map function setAllMap() { for (var i = 0; i < Gmarkers.length; i++) { Gmarkers[i].setMap(null); } } //Initialize the map function initialize() { var mapOptions = { center: new google.maps.LatLng(31.6, 0), zoom: 3, mapTypeId: google.maps.MapTypeId.TERRAIN }; map = new google.maps.Map(document.getElementById('map-canvas'),mapOptions); } google.maps.event.addDomListener(window, 'load', initialize); </script> </head> <body> <div id="json" class="shiny-html-output"></div> <button type="button" class="btn" id="hour" onClick="Shiny.onInputChange('Earth', 1)" style="position:absolute;top:1%;left:1%;width:100px;z-index:999">Last Hour</button> <button type="button" class="btn" id="day" onClick="Shiny.onInputChange('Earth', 2)" style="position:absolute;top:1%;left:10%;width:100px;z-index:999">Last Day</button> <button type="button" class="btn" id="week" onClick="Shiny.onInputChange('Earth', 3)" style="position:absolute;top:1%;left:20%;width:100px;z-index:999">Last Week</button> <button type="button" class="btn" id="month" onClick="Shiny.onInputChange('Earth', 4)" style="position:absolute;top:1%;left:30%;width:100px;z-index:999">Last Month</button> <div id="map-canvas" style="top:0%;right:0%;width:100%;height:100%;z-index:1"></div> </body> </html>Created with CodeFormatter
To leave a comment for the author, please follow the link and comment on their blog: R tutorial for Spatial Statistics.
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.