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)