Grids, Zonal Stats, Count by Polygons
In this lecture, we will continue to learn about spatial operations
We will use all these tools to make informed business decisisons
We will use some of the GIS operations that we learned. We will go over one practical example.
Let’s assume McDonald’s tries to open new restaurants in Rome Italy.
Like all profit-oriented companies, McDonald’s tries to minimize costs and maximize profit.
They are trying to open restaurants in areas:
Thus, as the good consultant that you are, you will use three data sources:
We will then perform GIS operations and make business recommendations.
This is what https:/overpass-turbo.eu/ looks like (2023/11/20).
We first zoom into the relevant area.
We then search for the relevant amenity: “restaurant”.
We then search for the relevant amenity: “restaurant”.
We then search for the relevant amenity: “restaurant”.
We then press “Run”.
We now see all the restaurant within the relevant area (that we zommed onto).
In this case we look for restaurants.
Other types of items that can be downloaded are available.
We should search for “amenity tag osm”.
Thus, the OSM wiki page will be helpful: https://wiki.openstreetmap.org/wiki/Map_features
We then download the data in geojson format by clicking “Export” in the Overpass-Turbo page.
Geojson is a format for encoding a variety of geographic data structures.
We then save the data in the relevant folder.
For consistency and to be able to have exactly the same result, download the restaurant data
Here is how we load the data. Note that I changed the name of the file from export.geojson to restaurant.geojson.
This is what the data looks like:
Rows: 2,931
Columns: 210
$ id <chr> "node/252440275", "node/252601050", "…
$ `@id` <chr> "node/252440275", "node/252601050", "…
$ FIXME <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `access:covid19` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `addr:city` <chr> "Roma", "Roma", "Roma", "Roma", NA, "…
$ `addr:country` <chr> NA, NA, "IT", "IT", NA, "IT", NA, NA,…
$ `addr:floor` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `addr:housename` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `addr:housenumber` <chr> "53", "33C", "88", "369/375", NA, "25…
$ `addr:postcode` <chr> "00153", "00184", "00186", "00146", N…
$ `addr:street` <chr> "Viale di Trastevere", "Via di San Ma…
$ `addr:suburb` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `addr:unit` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ air_conditioning <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ all_you_can_eat <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ alt_name <chr> NA, NA, "Filetti di baccalà", NA, NA,…
$ amenity <chr> "restaurant", "restaurant", "restaura…
$ amenity_1 <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ architect <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ bar <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ brand <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `brand:wikidata` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `brand:wikipedia` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ brewery <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ building <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `building:colour` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `building:levels` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `building:material` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `building:use` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ capacity <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `capacity:outdoor_seating` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ changing_table <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `changing_table:fee` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ check_date <date> NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ `check_date:currency:XBT` <date> NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ `check_date:opening_hours` <date> NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ club <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ comment <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `contact:email` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `contact:facebook` <chr> NA, "https://www.facebook.com/ristora…
$ `contact:foursquare` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `contact:google_plus` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `contact:housenumber` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `contact:instagram` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `contact:linkedin` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `contact:mobile` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `contact:phone` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `contact:pinterest` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `contact:postcode` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `contact:street` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `contact:tripadvisor` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `contact:twitter` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `contact:webform` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `contact:website` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `contact:whatsapp` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `contact:youtube` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ covered <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ created_by <chr> NA, NA, NA, NA, "Potlatch 0.8c", NA, …
$ cuisine <chr> "pizza", "chinese", "italian", "pizza…
$ `cuisine:fish` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `cuisine:pizza` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `cuisine:specialty` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ cuisine_1 <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `currency:XBT` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ delivery <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `delivery:covid19` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `delivery:description` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `delivery:partner` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ description <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `description:covid19` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `description:it` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ diet <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `diet:gluten_free` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `diet:halal` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `diet:kosher` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `diet:lactose_free` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `diet:meat` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `diet:mediterranean` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `diet:non-vegetarian` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `diet:organic` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `diet:vegan` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `diet:vegetarian` <chr> NA, "yes", NA, NA, NA, NA, NA, NA, NA…
$ dish <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ disused <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ drive_in <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ drive_through <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ ele <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ email <chr> NA, NA, NA, NA, NA, "bottiglieria@ait…
$ entrance <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ ethnicity <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ facebook <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ fax <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ fixme <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ highchair <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ ice_cream <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ image <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ indoor_seating <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ internet_access <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `internet_access:fee` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ kids_area <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `kids_area:fee` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `kids_area:indoor` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `kids_area:outdoor` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `kids_area:supervised` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ layer <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ level <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ lgbtq <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ live_music <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ lunch <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `lunch:buffet` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ mapillary <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ microbrewery <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ mobile <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ mobile_phone <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ name <chr> "Pizzeria ai Marmi", "Sichuan Haozi",…
$ `name:de` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `name:en` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `name:es` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `name:fr` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `name:it` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `name:ja` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `name:ko` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `name:nl` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `name:pt` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `name:ru` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `name:tr` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `name:zh` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ note <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `note:it` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ odbl <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ old_name <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `old_ref:vatin` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ old_website <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ opening_hours <chr> "Th-Tu 18:30-02:30", "Mo-Su 11:00-15:…
$ `opening_hours:covid19` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `opening_hours:kitchen` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `opening_hours:shop` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `opening_hours:signed` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ operator <chr> NA, NA, NA, "N.G.A. Srl.", NA, "Enote…
$ organic <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ outdoor <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ outdoor_seating <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ oven <chr> NA, NA, NA, "wood_fired", NA, NA, NA,…
$ owner <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ parking_space <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `payment:american_express` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `payment:apple_pay` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `payment:bancomat` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `payment:cards` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `payment:cash` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `payment:coins` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `payment:contactless` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `payment:credit_cards` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `payment:debit_cards` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `payment:girocard` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `payment:jcb` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `payment:maestro` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `payment:mastercard` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `payment:mastercard_contactless` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `payment:nfc` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `payment:notes` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `payment:v_pay` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `payment:visa` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `payment:visa_debit` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `payment:visa_electron` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ phone <chr> "+39 06 5800919", "+39 06 481 4425", …
$ phone2 <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `ref:IT:rea` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `ref:vatin` <chr> NA, NA, NA, "IT07728381000", NA, "IT0…
$ reservation <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ restaurant <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `restaurant:type` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `restaurant:type:it` <chr> NA, NA, NA, "pizzeria;bisteccheria;sf…
$ `roof:colour` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `roof:material` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `roof:orientation` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `roof:shape` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ self_service <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `sells:ice_cream` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ shop <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ slow_food <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ smoking <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `smoking:outside` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ source <chr> NA, NA, "Bing, Local knowledge", NA, …
$ stars <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ start_date <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `survey:date` <date> NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ takeaway <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `takeaway:covid19` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `takeaway:description` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ theme <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ toilets <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `toilets:access` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `toilets:wheelchair` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ tourism <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ type <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `type:it` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ url <chr> NA, NA, NA, NA, NA, "http://colosseoo…
$ vat <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ vatin <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ website <chr> "http://m.facebook.com/aimarmi", NA, …
$ `website:covid19` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `website:menu` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ `wetap:status` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ wheelchair <chr> NA, NA, NA, NA, NA, "no", NA, "limite…
$ `wheelchair:description` <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ wikidata <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ wikimedia_commons <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ wikipedia <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ geometry <POINT [°]> POINT (12.47379 41.88826), POIN…
This what these restaurants look like on the map.
You can download the background Rome data and central polygon.
library(sf)
library(ggplot2)
library(dplyr)
gis_buildings <- st_read(dsn="./data/selection.gdb",
layer="gis_osm_buildings", quiet = T)
gis_osm_roads <- st_read(dsn="./data/selection.gdb",
layer="gis_osm_roads", quiet = T)
gis_osm_pofw <- st_read(dsn="./data/selection.gdb",
layer="gis_osm_pofw", quiet = T)
gis_osm_pois <- st_read(dsn="./data/selection.gdb",
layer="gis_osm_pois", quiet = T)
relev_poly<-st_read(dsn="./data/central_polygon.shp", quiet = T)
st_crs(relev_poly)<-st_crs(gis_osm_pois)#Calculating polygon centroids
library("stringr")
error<-0.03
vatican <- subset(gis_osm_pofw, name=="Basilica di San Pietro")
vatican$lonlat<-st_centroid(st_geometry(vatican))
vatican[c('lon_x', 'lat_y')]<-str_split_fixed(vatican$lonlat, ",", 2)
vatican$lat_y<-as.numeric(str_replace(vatican$lat_y, "\\)", ""))
vatican$lon_x<-as.numeric(str_replace(vatican$lon_x, "c\\(", ""))
error<-0.03
min_lon_x<-min(vatican$lon_x-error)
max_lon_x<-max(vatican$lon_x+error)
min_lat_y<-min(vatican$lat_y-error)
max_lat_y<-max(vatican$lat_y+error)fig<-ggplot()+
geom_sf(data=relev_poly, linewidth = 0.1, fill = NA, color = "red", alpha=0.5)+
geom_sf(data=restaurants, color="blue", size=0.2)+
ggspatial::annotation_scale(location = 'tr')+
geom_sf(data=gis_osm_roads, linewidth = 0.1, color = "black", alpha=0.5)+
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())+
coord_sf(xlim = c(min_lon_x - error, max_lon_x + error),
ylim = c(min_lat_y - error, max_lat_y + error))
figWe can also search for fast-food restaurants.
We can also search for fast-food restaurants.
We can also search for fast-food restaurants.
For consistency and to be able to have exactly the same result, download the fast-food restaurants data
This what this data looks like using ggplot:
#Step1: Reading geojson
fastfood <- read_sf("./data/fast_food.geojson", quiet=TRUE)
fig<-ggplot()+
geom_sf(data=relev_poly, linewidth = 0.1, fill = NA, color = "red", alpha=0.5)+
ggspatial::annotation_scale(location = 'tr')+
geom_sf(data=gis_osm_roads, linewidth = 0.1, color = "black", alpha=0.5)+
geom_sf(data=fastfood, color="red", size=0.2)+
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())+
coord_sf(xlim = c(min_lon_x - error, max_lon_x + error),
ylim = c(min_lat_y - error, max_lat_y + error))
figWe have now selected all the fast-food restaurants.
However we want to simply select just the McDonald’s restaurants.
The problem is that there is no consistency about where the name “McDonald’s” is located:
We can now select McDonald’s from the list of fast-food restaurants.
We can now select McDonald’s from the list of fast-food restaurants.
We can go over every field and search for any word that has “mcdon” contained within.
#Step1: Reading geojson
fastfood <- read_sf("./data/fast_food.geojson", quiet=TRUE)
#Step2: Apply grepl function to each column and check for the presence of the word
row_indices_with_word <- apply(fastfood, 1, function(row) any(grepl("mcdon", row, ignore.case = TRUE)))
head(row_indices_with_word, 15) [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE
[13] TRUE TRUE TRUE
We can now select McDonald’s from the list of restaurants
This is the original data:
fig<-ggplot()+
geom_sf(data=relev_poly, linewidth = 0.1, fill = NA, color = "red", alpha=0.5)+
ggspatial::annotation_scale(location = 'tr')+
geom_sf(data=gis_osm_roads, linewidth = 0.1, color = "black", alpha=0.1)+
geom_sf(data=fastfood, color="red", size=0.2)+
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())+
coord_sf(xlim = c(min_lon_x - error, max_lon_x + error),
ylim = c(min_lat_y - error, max_lat_y + error))
figThis is only McDonald’s:
fig<-ggplot()+
geom_sf(data=relev_poly, linewidth = 0.1, fill = NA, color = "red", alpha=0.5)+
ggspatial::annotation_scale(location = 'tr')+
geom_sf(data=gis_osm_roads, linewidth = 0.1, color = "black", alpha=0.1)+
geom_sf(data=mcdon, color="yellow", size=0.5)+
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())+
coord_sf(xlim = c(min_lon_x - error, max_lon_x + error),
ylim = c(min_lat_y - error, max_lat_y + error))
figWe can download population density from SEDAC.
We can download population density from SEDAC.
We can download population density from SEDAC.
We can download population density from SEDAC.
We can download population density from SEDAC.
We can download population density from SEDAC.
We can download population density from SEDAC.
We can download population density from SEDAC.
We can download population density from SEDAC.
To save time, you can downlod the 2020 world population density data.
Reading the tif file
Reading the tif file
We now need to process the tif file to make it smaller (focus only on the region of interest).
Normal computers do not have enough memory to manipulate the data.
We will crop the world raster to only the tiny area around Rome.
This is the polygon depicted in red here.
We first need to identify the maximum latitude and longitude of this polygon
To obtain the four points, we need to identify the extreme points of the the central Rome polygon.
To obtain the four points, we need to use the following code.
'bbox' Named num [1:4] 12.4 41.8 12.6 42
- attr(*, "names")= chr [1:4] "xmin" "ymin" "xmax" "ymax"
- attr(*, "crs")=List of 2
..$ input: chr "WGS 84"
..$ wkt : chr "GEOGCRS[\"WGS 84\",\n ENSEMBLE[\"World Geodetic System 1984 ensemble\",\n MEMBER[\"World Geodetic Sys"| __truncated__
..- attr(*, "class")= chr "crs"
The extent of the original raster
'bbox' Named num [1:4] -180 -90 180 90
- attr(*, "names")= chr [1:4] "xmin" "ymin" "xmax" "ymax"
- attr(*, "crs")=List of 2
..$ input: chr "WGS 84"
..$ wkt : chr "GEOGCRS[\"WGS 84\",\n ENSEMBLE[\"World Geodetic System 1984 ensemble\",\n MEMBER[\"World Geodetic Sys"| __truncated__
..- attr(*, "class")= chr "crs"
We now finally crop the raster
This is how the two rasters compare
This is how the two rasters compare
We now want to transform the picture (raster) into a feature polygon.
In our case, we want to turn our raster into polygon grids.
In our case, there are no differences between a raster and a polygon feature based on that raster.
Visually, there are no differences between a raster and a polygon feature based on that raster.
However, the raster is a picture (tif file), while the polygon feature is a shape file.
This is how we turn the raster into a grid polygon
We can now map the new grid
We can calculate grid centroid in order to display the value of the raster.
We can calculate grid centroid in order to display the value of the raster.
Mapping grid values
#Step1: Preparing the labels
g2$pop2<-round(g2$pop,1)
#Step2: Mapping the data
fig<-ggplot()+
geom_sf(data=g2, aes(fill=pop), color=NA, alpha=0.6)+
scale_fill_viridis_c(option = "magma",begin = 0.1)+
coord_sf(xlim = c(min_lon_x - error, max_lon_x + error),
ylim = c(min_lat_y - error, max_lat_y + error))+
geom_sf_text(data=g2, aes(label=pop2),size=1)+
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())+
ggspatial::annotation_scale(location = 'tr')Mapping grid values
fig<-ggplot()+
geom_sf(data=g2, aes(fill=pop), color=NA, alpha=0.6)+
scale_fill_viridis_c(option = "magma",begin = 0.1)+
geom_sf(data=relev_poly, linewidth = 0.1, fill = NA, color = "red", alpha=0.5)+
geom_sf(data=gis_osm_roads, linewidth = 0.1, color = "black", alpha=0.5)+
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())+
coord_sf(xlim = c(min_lon_x - error, max_lon_x + error),
ylim = c(min_lat_y - error, max_lat_y + error))+
ggspatial::annotation_scale(location = 'tr')fig<-ggplot()+
geom_sf(data=g2, aes(fill=pop), color=NA, alpha=0.6)+
scale_fill_viridis_c(option = "magma",begin = 0.1)+
geom_sf(data=relev_poly, linewidth = 0.1, fill = NA, color = "red", alpha=0.5)+
geom_sf(data=restaurants2, color="blue", size=0.2)+
geom_sf(data=gis_osm_roads, linewidth = 0.1, color = "black", alpha=0.5)+
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())+
coord_sf(xlim = c(min_lon_x - error, max_lon_x + error),
ylim = c(min_lat_y - error, max_lat_y + error))+
ggspatial::annotation_scale(location = 'tr')fig<-ggplot()+
geom_sf(data=g2, aes(fill=pop), color=NA, alpha=0.6)+
scale_fill_viridis_c(option = "magma",begin = 0.1)+
geom_sf(data=relev_poly, linewidth = 0.1, fill = NA, color = "red", alpha=0.5)+
geom_sf(data=restaurants2, color="blue", size=0.2)+
geom_sf(data=mcdon, color="yellow", size=0.8)+
geom_sf(data=gis_osm_roads, linewidth = 0.1, color = "black", alpha=0.5)+
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())+
coord_sf(xlim = c(min_lon_x - error, max_lon_x + error),
ylim = c(min_lat_y - error, max_lat_y + error))+
ggspatial::annotation_scale(location = 'tr')g2$pop<-round(g2$pop,2)
g3 <- g2 %>%
mutate(rest = lengths(st_intersects(., restaurants2)),
mc = lengths(st_intersects(., mcdon)))
g3$rest_per_1000ppl<-g3$rest/g3$pop*1000
g3$rest_per_1000ppl<-round(g3$rest_per_1000ppl,2)
g3$mc_per_1000ppl<-g3$mc/g3$pop*1000
g3$mc_per_1000ppl<-round(g3$mc_per_1000ppl,2)
head(g3, 3)Mapping restaurants in a grid:
fig1<-ggplot()+
geom_sf(data=g3, aes(fill=rest), color=NA, alpha=0.6)+
scale_fill_viridis_c(option = "magma",begin = 0.1)+
geom_sf(data=relev_poly, linewidth = 0.1, fill = NA, color = "red", alpha=0.5)+
geom_sf(data=restaurants2, color="blue", size=0.2)+
geom_sf(data=mcdon, color="yellow", size=0.8)+
ggspatial::annotation_scale(location = 'tr')+
geom_sf(data=gis_osm_roads, linewidth = 0.1, color = "black", alpha=0.5)+
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())+
coord_sf(xlim = c(min_lon_x - error, max_lon_x + error),
ylim = c(min_lat_y - error, max_lat_y + error))Mapping restaurants in a grid:
Mapping log restaurants + 1 in a grid:
fig2<-ggplot()+
geom_sf(data=g3, aes(fill=log(rest+1)), color=NA, alpha=0.6)+
scale_fill_viridis_c(option = "magma",begin = 0.1)+
geom_sf(data=relev_poly, linewidth = 0.1, fill = NA, color = "red", alpha=0.5)+
geom_sf(data=restaurants2, color="blue", size=0.2)+
geom_sf(data=mcdon, color="yellow", size=0.8)+
ggspatial::annotation_scale(location = 'tr')+
geom_sf(data=gis_osm_roads, linewidth = 0.1, color = "black", alpha=0.5)+
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())+
coord_sf(xlim = c(min_lon_x - error, max_lon_x + error),
ylim = c(min_lat_y - error, max_lat_y + error))Mapping log restaurants + 1 in a grid:
Notice the difference
library(ggpubr)
library(lemon)
fig1<-ggplot()+
geom_sf(data=g3, aes(fill=rest), color=NA, alpha=0.6)+
scale_fill_viridis_c(option = "magma",begin = 0.1)+
geom_sf(data=relev_poly, linewidth = 0.1, fill = NA, color = "red", alpha=0.5)+
geom_sf(data=restaurants2, color="blue", size=0.2)+
geom_sf(data=mcdon, color="yellow", size=0.8)+
ggspatial::annotation_scale(location = 'tr')+
geom_sf(data=gis_osm_roads, linewidth = 0.1, color = "black", alpha=0.5)+
coord_sf(xlim = c(min_lon_x - error, max_lon_x + error),
ylim = c(min_lat_y - error, max_lat_y + error))+
theme(axis.title = element_blank(), # Remove axis titles
axis.ticks = element_blank(),
legend.box.background = element_rect(fill = "white",
linewidth=0.5, linetype="solid",
colour = "black"),
legend.position = c(0, 1),
legend.justification = c(0, 1))
fig2<-ggplot()+
geom_sf(data=g3, aes(fill=log(rest+1)), color=NA, alpha=0.6)+
scale_fill_viridis_c(option = "magma",begin = 0.1)+
geom_sf(data=relev_poly, linewidth = 0.1, fill = NA, color = "red", alpha=0.5)+
geom_sf(data=restaurants2, color="blue", size=0.2)+
geom_sf(data=mcdon, color="yellow", size=0.8)+
ggspatial::annotation_scale(location = 'tr')+
geom_sf(data=gis_osm_roads, linewidth = 0.1, color = "black", alpha=0.5)+
coord_sf(xlim = c(min_lon_x - error, max_lon_x + error),
ylim = c(min_lat_y - error, max_lat_y + error))+
theme(axis.title = element_blank(), # Remove axis titles
axis.ticks = element_blank(),
legend.box.background = element_rect(fill = "white",
linewidth=0.5, linetype="solid",
colour = "black"),
legend.position = c(0, 1),
legend.justification = c(0, 1))
ggarrange(fig1, fig2, ncol=2)Notice also the difference in the distribution of the two
Mapping log restaurants per thousand people + 1 in a grid:
fig<-ggplot()+
geom_sf(data=g3, aes(fill=log(rest_per_1000ppl+1)), color=NA, alpha=0.6)+
scale_fill_viridis_c(option = "magma",begin = 0.1)+
geom_sf(data=relev_poly, linewidth = 0.1, fill = NA, color = "red", alpha=0.5)+
geom_sf(data=restaurants2, color="blue", size=0.2)+
geom_sf(data=mcdon, color="yellow", size=0.8)+
ggspatial::annotation_scale(location = 'tr')+
geom_sf(data=gis_osm_roads, linewidth = 0.1, color = "black", alpha=0.5)+
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())+
coord_sf(xlim = c(min_lon_x - error, max_lon_x + error),
ylim = c(min_lat_y - error, max_lat_y + error))Mapping log restaurants per thousand people + 1 in a grid:
Mapping log McDonald’s restaurants per thousand people + 1 in a grid:
fig<-ggplot()+
geom_sf(data=g3, aes(fill=log(mc_per_1000ppl+1)), color=NA, alpha=0.6)+
scale_fill_viridis_c(option = "magma",begin = 0.1)+
geom_sf(data=relev_poly, linewidth = 0.1, fill = NA, color = "red", alpha=0.5)+
geom_sf(data=restaurants2, color="blue", size=0.2)+
geom_sf(data=mcdon, color="yellow", size=0.8)+
ggspatial::annotation_scale(location = 'tr')+
geom_sf(data=gis_osm_roads, linewidth = 0.1, color = "black", alpha=0.5)+
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())+
coord_sf(xlim = c(min_lon_x - error, max_lon_x + error),
ylim = c(min_lat_y - error, max_lat_y + error))Mapping log McDonald’s restaurants per thousand people + 1 in a grid:
Let us assume that our business decision relies on the following criteria:
Note that these numbers are arbitrary here. We can obviously change these parameters.
manypeople<-subset(g3, pop>1000 & mc==0 & rest>=1 & rest<50)
fig<-ggplot()+
geom_sf(data=manypeople, aes(fill=log(pop+1)), color=NA, alpha=0.6)+
scale_fill_viridis_c(option = "magma",begin = 0.1)+
geom_sf(data=relev_poly, linewidth = 0.1, fill = NA, color = "red", alpha=0.5)+
geom_sf(data=restaurants2, color="blue", size=0.2)+
geom_sf(data=mcdon, color="yellow", size=0.8)+
ggspatial::annotation_scale(location = 'tr')+
geom_sf(data=gis_osm_roads, linewidth = 0.1, color = "black", alpha=0.5)+
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())+
coord_sf(xlim = c(min_lon_x - error, max_lon_x + error),
ylim = c(min_lat_y - error, max_lat_y + error))Finllay, we want something within 3 km from the Vatican
vatican <- subset(gis_osm_pofw, name=="Basilica di San Pietro")
vatican$lonlat<-st_centroid(st_geometry(vatican))
vatican[c('lon_x', 'lat_y')]<-str_split_fixed(vatican$lonlat, ",", 2)
vatican$lat_y<-as.numeric(str_replace(vatican$lat_y, "\\)", ""))
vatican$lon_x<-as.numeric(str_replace(vatican$lon_x, "c\\(", ""))
vatican1<-subset(vatican, select = c(name))
fig<-ggplot()+
geom_sf(data=manypeople, aes(fill=log(pop+1)), color=NA, alpha=0.6)+
scale_fill_viridis_c(option = "magma",begin = 0.1)+
geom_sf(data=relev_poly, linewidth = 0.1, fill = NA, color = "red", alpha=0.5)+
geom_sf(data=restaurants2, color="blue", size=0.2)+
geom_sf(data=mcdon, color="yellow", size=0.8)+
geom_sf(data=vatican1, color="green")+
ggspatial::annotation_scale(location = 'tr')+
geom_sf(data=gis_osm_roads, linewidth = 0.1, color = "black", alpha=0.5)+
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())+
coord_sf(xlim = c(min_lon_x - error, max_lon_x + error),
ylim = c(min_lat_y - error, max_lat_y + error))Finally, we want something within 3 km from the Vatican
#Creating the 3km buffer
#Step1: Turning the relevant shape to a metric systems
vatican_reproj = st_transform(vatican, 6875)
#Step2: Creating the 3km
vatican_buff <- st_buffer(vatican_reproj, dist = 3000)
#Step3: Turning back to WGS84
vatican_buff2<-st_transform(st_as_sf(vatican_buff), st_crs(vatican))fig<-ggplot()+
geom_sf(data=manypeople, aes(fill=log(pop+1)), color=NA, alpha=0.6)+
scale_fill_viridis_c(option = "magma",begin = 0.1)+
geom_sf(data=relev_poly, linewidth = 0.1, fill = NA, color = "red", alpha=0.5)+
geom_sf(data=restaurants2, color="blue", size=0.2)+
geom_sf(data=mcdon, color="yellow", size=0.8)+
geom_sf(data=vatican1, color="chartreuse3")+
geom_sf(data=vatican_buff2, color="chartreuse3", fill=NA, linewidth=1)+
ggspatial::annotation_scale(location = 'tr')+
geom_sf(data=gis_osm_roads, linewidth = 0.1, color = "black", alpha=0.5)+
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())+
coord_sf(xlim = c(min_lon_x - error, max_lon_x + error),
ylim = c(min_lat_y - error, max_lat_y + error))fig<-ggplot()+
geom_sf(data=manypeople, aes(fill=log(pop+1)), color=NA, alpha=0.6)+
geom_sf(data=sf_inters, color="red", linewidth = 1, fill=NA, alpha=0.6)+
scale_fill_viridis_c(option = "magma",begin = 0.1)+
geom_sf(data=gis_osm_roads, linewidth = 0.1, color = "black", alpha=0.5)+
geom_sf(data=relev_poly, linewidth = 0.1, fill = NA, color = "red", alpha=0.5)+
geom_sf(data=restaurants2, color="blue", size=0.2)+
geom_sf(data=mcdon, color="yellow", size=0.8)+
geom_sf(data=vatican1, color="chartreuse3")+
geom_sf(data=vatican_buff2, color="chartreuse3", fill=NA, linewidth=1)+
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())+
coord_sf(xlim = c(min_lon_x - error, max_lon_x + error),
ylim = c(min_lat_y - error, max_lat_y + error))+
ggspatial::annotation_scale(location = 'tr')Let us now simply plot those areas
Let us now simply plot those areas
We have revisited a few GIS tools during this lecture:
Popescu (JCU): Lecture 19