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.
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
<- "YOUR_GOOGLE_API_KEY"
google_key # bounding box limits for map
<- 47.565
top_lat <- 47.54
bottom_lat <- 7.57
left_lng <- 7.61
right_lng =13 # resolution of map
zoom_level# steps for grid
= 20
steps # thing to search for
=bar
type# see link for full list
# https://developers.google.com/places/supported_types
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.
<- function(
jb_pullnearby GOOGLE_API_KEY = google_key,
# 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_SE-lat_NW)/steps
lat_incr = (lng_SE-lng_NW)/steps
lng_incr # Start in the northwest and iterate to the southeast
= lat_NW
lat_curr = lng_NW
lng_curr
# clear output
<- NULL
data_output
# Open loop
for(i_lat in 1:steps){
for(i_lng in 1:steps){
# current location
= paste0(lat_curr,",",lng_curr)
curr_location # url to call api
<- paste0('https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=',
url
curr_location,'&key=',
GOOGLE_API_KEY,'&rankby=distance&types=',
type)<- fromJSON(txt=url)$results
response if(!is.null(nrow(response))){
<- response$geometry$location
temp_location <- response %>%
temp_info select(place_id,icon,name,vicinity)
<- cbind(temp_location,temp_info)
temp_data # 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
<- rbind(data_output,temp_data)
data_output
}# Move along one lng increment
<- lng_curr+lng_incr
lng_curr # longitiude loop
} # reset longitude
= lng_NW
lng_curr # Move along one lat increment
<- lat_curr+lat_incr
lat_curr # 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.
<- function(
jb_googledist origin=paste0(lat,",",lng),
destination=paste0(lat,",",lng),
GOOGLE_API_KEY=google_key){
library(XML)
library(RCurl)
<- paste0(
xml.url 'https://maps.googleapis.com/maps/api/distancematrix/xml?origins=',
'&destinations=',
origin,
destination,'&mode=walking&key=',
GOOGLE_API_KEY,'&sensor=false')
<- xmlParse(getURL(xml.url))
xmlfile <- xmlValue(xmlChildren(xpathApply(xmlfile,"//duration")[[1]])$value)
time <- round(as.numeric(time)/60,1)
time <- xmlValue(xmlChildren(xpathApply(xmlfile,"//distance")[[1]])$value)
dist <- as.numeric(dist)
distance <- data.frame(time=time,distance=distance)
output 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
<- jb_pullnearby(
data_locations 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
<- data_locations %>%
dataset filter(n==1)
# Get google distance
# empty results df
<- NULL
dataset_distances # start loop over data
for(i in 1:nrow(dataset)){
# current iteration
= paste0(dataset$lat[i],",",dataset$lng[i])
i_origin = paste0(dataset$loc_lat[i],",",dataset$loc_lng[i])
i_destination # get distances
<- jb_googledist(
i_distance origin=i_origin,
destination=i_destination,
GOOGLE_API_KEY = google_key)
# load into data
<- rbind(dataset_distances,i_distance)
dataset_distances
}# add to data
<- cbind(dataset,dataset_distances)
dataset
# map it
library(ggmap)
## get the map from stamen
<- get_stamenmap(
basemap 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[order(-dataset$distance),]
dataset
# 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) +
scale_colour_gradient(limits=c(0, 2500),
low="blue", high="red")+
geom_point(aes(x=dataset$loc_lng,
y=dataset$loc_lat),size=3)
ggsave("map.svg", width=10, height=10)