I’ll be heading to the 2016 ROpenSci un-conference (auunconf.ropensci.org) (hackathon) in Brisbane later this month to smash out a heap of open-science R code. Ideas are already flowing quite nicely, and I’m confident that any ideas we don’t end up officially working on will get their chance in the very near future.
One thing I noticed from the organisers was that coffee won’t be provided in an official sense. As a physicist at heart, that’s strange (scary) yet understandable (physics conferences go through an astounding amount of coffee; we once had a full-time barista on deck). There are supposedly plenty of nearby places to get a good coffee, but where? Time for some R code!
| # myAPIkey <- "PlAcEyOuRkEyHeRe" | |
| library(ggplot2) | |
| library(ggmap) | |
| library(ggthemes) | |
| library(png) | |
| library(grid) | |
| library(RCurl) | |
| findXnearY <- function(X = "coffee", # default: coffee | |
| Y = data.frame(lat=-34.9286, lon=138.6000), # default: Adelaide | |
| likelyType = "food|restaurant|cafe", | |
| radius = 1000, # default: 1km | |
| APIkey = NULL, | |
| ...) { | |
| #' X :: [chr] a keyword to search for | |
| #' Y :: [data.frame] a location (lat/lon pair) | |
| #' LikelyType :: [chr] type of location (e.g. "food|restaurant|cafe") | |
| #' radius :: [int] search radius [m] | |
| #' APIkey :: [chr] Google app API key (private) | |
| library(jsonlite) # fromJSON | |
| if(is.null(APIkey)) | |
| stop("requires a Google API key. Get one here: | |
| https://developers.google.com/maps/documentation/javascript/get-api-key") | |
| location <- paste(Y$lat[1], Y$lon[1], sep=",") | |
| ## Google Places API endpoint | |
| APIendpoint <- "https://maps.googleapis.com/maps/api/place/nearbysearch/json" | |
| ## construct API call | |
| APIURL <- paste0(APIendpoint, | |
| "?location=", location, | |
| "&radius=", radius, | |
| "&types=", likelyType, | |
| "&keyword=", X, | |
| "&key=", APIkey) | |
| cat(paste0("Fetching: ",APIURL)) | |
| places <- fromJSON(APIURL) | |
| result <- data.frame(name=places$results$name, | |
| lat=places$results$geometry$location$lat, | |
| lon=places$results$geometry$location$lng) | |
| return(result) | |
| } | |
| ## Microsoft Innovation Centre (MIC) | |
| MIC <- data.frame(lat=-27.468331, lon=153.020899) | |
| ## fetch results for coffee near the MIC | |
| coffee <- findXnearY(X = "coffee", | |
| Y = MIC, | |
| likelyType = "food|restaurant|cafe", | |
| radius = 1000, | |
| APIkey = myAPIkey) | |
| ## fetch a map of Brisbane, centered at the MIC from Google Maps | |
| Bris.map = get_map(location=MIC, zoom=16, color="bw") | |
| ## fetch a .png of the R logo | |
| RPNG <- readPNG(getURLContent("https://www.r-project.org/logo/Rlogo.png")) | |
| RGROB <- rasterGrob(RPNG, interpolate=TRUE) | |
| offsetR <- 0.0006 | |
| ## fetch a .png of a decent takeaway coffee cup | |
| coffeePNG <- readPNG(getURLContent("http://www.megaicons.net/static/img/icons_sizes/8/60/256/kitchen-coffee-to-go-icon.png")) | |
| coffeeGROB <- rasterGrob(coffeePNG, interpolate=TRUE) | |
| offsetCoffee <- 0.0003 | |
| ## construct the map with a 2d density around the coffee locations | |
| gg <- ggmap(Bris.map) | |
| gg <- gg + coord_cartesian(xlim=c(attr(Bris.map, "bb")$ll.lon, | |
| attr(Bris.map, "bb")$ur.lon), | |
| ylim=c(attr(Bris.map, "bb")$ll.lat, | |
| attr(Bris.map, "bb")$ur.lat)) | |
| gg <- gg + geom_density2d(data=coffee, aes(x=lon, y=lat), size=1) | |
| gg <- gg + mapply(function(xx, yy) | |
| annotation_custom(coffeeGROB, | |
| xmin=xx-offsetCoffee, | |
| xmax=xx+offsetCoffee, | |
| ymin=yy-offsetCoffee, | |
| ymax=yy+offsetCoffee), | |
| coffee$lon, coffee$lat) | |
| gg <- gg + annotation_custom(RGROB, | |
| xmin=MIC$lon-offsetR, | |
| xmax=MIC$lon+offsetR, | |
| ymin=MIC$lat-offsetR, | |
| ymax=MIC$lat+offsetR) | |
| gg <- gg + theme_map() | |
| gg <- gg + theme(text=element_text(size=22)) | |
| gg <- gg + labs(title="Coffee!", | |
| subtitle="Walking distance from #auunconf @ Microsoft Innovation Centre", | |
| caption="J. Carroll, 2016, www.jcarroll.com.au") | |
| gg | |
| ## output the image | |
| png("coffee_near_auunconf_2016.png", width=2400, height=2400, res=300) | |
| gg | |
| dev.off() | |
| name lat lon | |
| 1 Starbucks -27.47030 153.0257 | |
| 2 Cartel Coffee -27.46826 153.0248 | |
| 3 Merlo Coffee -27.47017 153.0233 | |
| 4 Dancing Bean Espresso -27.46649 153.0188 | |
| 5 Gramercy Coffee -27.46896 153.0272 | |
| 6 Zarraffa's Coffee Myer Centre -27.47107 153.0252 | |
| 7 Alen's Espresso -27.46787 153.0204 | |
| 8 Naked Coffee -27.47101 153.0254 | |
| 9 Nespresso Boutique Brisbane -27.46856 153.0266 | |
| 10 Stellarossa Albert Lane -27.46973 153.0260 | |
| 11 Hudsons Coffee -27.46478 153.0226 | |
| 12 The Frisky Goat Espresso -27.47174 153.0247 | |
| 13 Keri Craig Emporium - Homewares, Fashion, Coffee Lounge -27.46863 153.0250 | |
| 14 Transit Coffee Lounge -27.46633 153.0188 | |
| 15 BarMerlo -27.46658 153.0290 | |
| 16 Toby's Estate Espresso Bar -27.47219 153.0279 | |
| 17 Bacano Coffee -27.46966 153.0292 | |
| 18 Is Funk Coffee & Food -27.46699 153.0291 | |
| 19 Two Trees -27.47377 153.0160 | |
| 20 Cartel Coffee -27.47204 153.0265 |
This ended up being a little easier than I first thought thanks to someone already identifying the right Google Places API endpoint and providing an example function (stackoverflow.com). I re-wrote the function to be a bit more general and to suit my needs a little better. After that it’s just a matter of extracting and plotting locations, adding a 2d density, and prettifying the output.

I’m loving hrbrmstr’s annotations additions (rud.is) to ggplot2; I think they really bring R graphics into a professional appearance. I have a feeling that my locations when not at the hackathon itself will correlate well with this density map as I try to find the best local coffee.
Stay tuned for updates on the projects we end up developing. I have a good feeling that they’re going to be somewhat awesome.
Suggestions on the above code most welcome. Also, if you happen to know of a great coffee house near there that isn’t listed, hit the comments section!