# Data science art

Tina and I recently moved into a new apartment in Basel. Currently, our walls are completely bare - so I thought it would be cool to use the Google maps API to try and make a wall hanging based off Basel location data. I’ve wrapped up all the code to make these plots in a function, and details on how to run the code is here.

The final result is this.

And a close up..

Which I made with this code…

## Variables that change

Below are the master inputs that need to be set. This can easily be edited for more specific searches. For example, in the supermarket plot above, I added in name=coop|migros to limit the search to only the two major supermarket chains (so no budget or ethnic supermarkets are in that plot).

# Variables to input
# bounding box limits for map
top_lat <- 47.565
bottom_lat <- 47.54
left_lng <- 7.57
right_lng <- 7.61
zoom_level=13 # resolution of map
# steps for grid
steps = 20
# thing to search for
type=bar
# see link for full list
{% endhighlight %}

## Functions

### Pull nearest amenity

This function will take the location frame you give it, make a grid (the number of points defined by steps) and get the closest type of place you are looking for.

{% highlight r %}
jb_pullnearby <- function(
# Map corners
lat_NW = 47.56232,
lng_NW = 7.57373,
lat_SE = 47.54263,
lng_SE = 7.60274,
steps=100,
type="restaurant"
){
library(jsonlite)
library(dplyr)

# 100 steps left and 100 down
lat_incr = (lat_SE-lat_NW)/steps
lng_incr = (lng_SE-lng_NW)/steps
# Start in the northwest and iterate to the southeast
lat_curr = lat_NW
lng_curr = lng_NW

# clear output
data_output <- NULL

# Open loop

for(i_lat in 1:steps){
for(i_lng in 1:steps){
# current location
curr_location = paste0(lat_curr,",",lng_curr)
# url to call api
curr_location,
'&key=',
'&rankby=distance&types=',
type)
response <- fromJSON(txt=url)$results if(!is.null(nrow(response))){ temp_location <- response$geometry$location temp_info <- response %>% select(place_id,icon,name,vicinity) temp_data <- cbind(temp_location,temp_info) # Make line of data from response # note rankby means sorted by proxomity! temp_data <- temp_data %>% mutate( n = 1:n(), loc_lat = lat, loc_lng = lng, lat = lat_curr, lng = lng_curr, i_lat = i_lat, i_lng = i_lng ) # add data data_output <- rbind(data_output,temp_data) } # Move along one lng increment lng_curr <- lng_curr+lng_incr } # longitiude loop # reset longitude lng_curr = lng_NW # Move along one lat increment lat_curr <- lat_curr+lat_incr } # latitude loop return(data_output) } # close function ### Get walking time and distance This function will take two locations and get back the walking time and distance from Google. jb_googledist <- function( origin=paste0(lat,",",lng), destination=paste0(lat,",",lng), GOOGLE_API_KEY=google_key){ library(XML) library(RCurl) xml.url <- paste0( 'https://maps.googleapis.com/maps/api/distancematrix/xml?origins=', origin,'&destinations=', destination, '&mode=walking&key=', GOOGLE_API_KEY, '&sensor=false') xmlfile <- xmlParse(getURL(xml.url)) time <- xmlValue(xmlChildren(xpathApply(xmlfile,"//duration")[[1]])$value)
time <- round(as.numeric(time)/60,1)
dist <- xmlValue(xmlChildren(xpathApply(xmlfile,"//distance")[[1]])$value) distance <- as.numeric(dist) output <- data.frame(time=time,distance=distance) return(output) } ## Run functions and plot This final code is an example of how to use the two functions to make a plot like the three above. The first code block (with the changing inputs needs to also be run, as this code uses those inputs). # Get the nearest data_locations <- jb_pullnearby( GOOGLE_API_KEY = google_key, # Map corners lat_NW = top_lat, lng_NW = left_lng, lat_SE = bottom_lat, lng_SE = right_lng, steps=steps, type=type ) # Drop to closest restaurant dataset <- data_locations %>% filter(n==1) # Get google distance # empty results df dataset_distances <- NULL # start loop over data for(i in 1:nrow(dataset)){ # current iteration i_origin = paste0(dataset$lat[i],",",dataset$lng[i]) i_destination = paste0(dataset$loc_lat[i],",",dataset$loc_lng[i]) # get distances i_distance <- jb_googledist( origin=i_origin, destination=i_destination, GOOGLE_API_KEY = google_key) # load into data dataset_distances <- rbind(dataset_distances,i_distance) } # add to data dataset <- cbind(dataset,dataset_distances) # map it library(ggmap) ## get the map from stamen basemap <- get_stamenmap( bbox = c(left = left_lng, bottom = bottom_lat, right = right_lng, top = top_lat), zoom=zoom_level, source='stamen',crop = TRUE, maptype="terrain-lines", color="bw") # Order points high to low dataset <- dataset[order(-dataset$distance),]

# Plot - pubs
ggmap(basemap,extent = 'device') +
geom_segment(
aes(x=lng, xend=loc_lng,
y=lat, yend=loc_lat,
colour=distance,
alpha=0.5),
size=2, data=dataset) +
geom_point(aes(x=dataset$loc_lng, y=dataset$loc_lat),size=3)
ggsave("map.svg", width=10, height=10)