library(sf)
library(tidyverse)
library(tmap)
setwd("C:/Users/bonwo/Dropbox (Personal)/School/CP6025/lecture/11262019_sf")
Â
In order to read a shapefile as an sf object in R, use st_read() function. At minimum, it needs only one argument - the name (or the path) of the shapefile.
To write, you can use st_write() function. It needs two arguments (1) name of an sf object and (2) the name of the shapefile you want to save. See below for an example. This st_write() function will create 4 files because a shapefile is actually a collection of multiple files.
# Reading sf data
sf.data <- st_read("sf_example.shp")
## Reading layer `sf_example' from data source `C:\Users\bonwo\Dropbox (Personal)\School\CP6025\lecture\11262019_sf\sf_example.shp' using driver `ESRI Shapefile'
## Simple feature collection with 501 features and 16 fields
## geometry type: POLYGON
## dimension: XY
## bbox: xmin: 636450.8 ymin: 371709.7 xmax: 713243.6 ymax: 464175.8
## epsg (SRID): NA
## proj4string: +proj=tmerc +lat_0=30 +lon_0=-84.16666666666667 +k=0.9999 +x_0=700000 +y_0=0 +ellps=GRS80 +units=m +no_defs
cbd <- st_read("city_hall_5mile.shp")
## Reading layer `city_hall_5mile' from data source `C:\Users\bonwo\Dropbox (Personal)\School\CP6025\lecture\11262019_sf\city_hall_5mile.shp' using driver `ESRI Shapefile'
## Simple feature collection with 1 feature and 1 field
## geometry type: POLYGON
## dimension: XY
## bbox: xmin: 671494.3 ymin: 407687.5 xmax: 687494.3 ymax: 423687.5
## epsg (SRID): NA
## proj4string: +proj=tmerc +lat_0=30 +lon_0=-84.16666666666667 +k=0.9999 +x_0=700000 +y_0=0 +ellps=GRS80 +units=m +no_defs
# Writing sf data (I commented it out because we don't need to actually save it)
# st_write(sf.data, "sf_data_from_R.shp")
Â
You can print out the content of a sf object the same way as you would with ordinary data.frame. You can also use print() function to control what the output looks like. For example, width argument in print() function allows you to deteremine how long you want the print to be. In our example, however, it is not meaningful because we don’t have that many variables in the first place.
# Printing sf data.
sf.data
## Simple feature collection with 501 features and 16 fields
## geometry type: POLYGON
## dimension: XY
## bbox: xmin: 636450.8 ymin: 371709.7 xmax: 713243.6 ymax: 464175.8
## epsg (SRID): NA
## proj4string: +proj=tmerc +lat_0=30 +lon_0=-84.16666666666667 +k=0.9999 +x_0=700000 +y_0=0 +ellps=GRS80 +units=m +no_defs
## First 10 features:
## GEOID n walkscr tract county state mval
## 1 13063040202 75 18.81333 Census Tract 402.02 Clayton County Georgia 98600
## 2 13063040203 24 26.16667 Census Tract 402.03 Clayton County Georgia 98200
## 3 13063040204 20 37.40000 Census Tract 402.04 Clayton County Georgia 105000
## 4 13063040302 45 31.66667 Census Tract 403.02 Clayton County Georgia 55400
## 5 13063040303 45 33.42222 Census Tract 403.03 Clayton County Georgia 59300
## 6 13063040307 24 22.70833 Census Tract 403.07 Clayton County Georgia 69100
## 7 13063040308 74 26.32432 Census Tract 403.08 Clayton County Georgia 60500
## 8 13063040407 70 17.81429 Census Tract 404.07 Clayton County Georgia 89700
## 9 13063040408 51 26.47059 Census Tract 404.08 Clayton County Georgia 99200
## 10 13063040409 32 20.43750 Census Tract 404.09 Clayton County Georgia 88100
## hinc nroom unt_sng unt_mlt untstr_ p_singl p_multi cbd_dst in_atl
## 1 31524 5.6 614 397 1011 0.6073195 0.39268051 12908.51 0
## 2 36786 5.2 992 704 1696 0.5849057 0.41509434 15682.62 0
## 3 39194 4.5 843 1210 2064 0.4084302 0.58624031 15358.93 0
## 4 33190 4.9 1447 876 2323 0.6229014 0.37709858 11214.80 1
## 5 37236 5.4 2047 629 2730 0.7498168 0.23040293 11418.21 1
## 6 37064 6.2 1659 86 1772 0.9362302 0.04853273 15944.66 0
## 7 25159 4.7 1253 752 2038 0.6148184 0.36898921 11189.45 1
## 8 45768 5.5 1315 98 1465 0.8976109 0.06689420 14795.19 0
## 9 37224 5.6 1442 1408 2891 0.4987893 0.48702871 16444.02 0
## 10 42280 6.1 1880 221 2129 0.8830437 0.10380460 18062.68 0
## geometry
## 1 POLYGON ((674775.5 401071.4...
## 2 POLYGON ((672913.4 399171.9...
## 3 POLYGON ((673731.3 401102.2...
## 4 POLYGON ((679467.3 402730.3...
## 5 POLYGON ((681575.2 404460.5...
## 6 POLYGON ((680718 399789.9, ...
## 7 POLYGON ((678214.8 403283.3...
## 8 POLYGON ((681714.8 400107.7...
## 9 POLYGON ((682498.2 399520.2...
## 10 POLYGON ((686028.5 398774.5...
# The width argument is useful when there are many columns but not so much right now.
print(sf.data, width = 100)
## Simple feature collection with 501 features and 16 fields
## geometry type: POLYGON
## dimension: XY
## bbox: xmin: 636450.8 ymin: 371709.7 xmax: 713243.6 ymax: 464175.8
## epsg (SRID): NA
## proj4string: +proj=tmerc +lat_0=30 +lon_0=-84.16666666666667 +k=0.9999 +x_0=700000 +y_0=0 +ellps=GRS80 +units=m +no_defs
## First 10 features:
## GEOID n walkscr tract county state mval
## 1 13063040202 75 18.81333 Census Tract 402.02 Clayton County Georgia 98600
## 2 13063040203 24 26.16667 Census Tract 402.03 Clayton County Georgia 98200
## 3 13063040204 20 37.40000 Census Tract 402.04 Clayton County Georgia 105000
## 4 13063040302 45 31.66667 Census Tract 403.02 Clayton County Georgia 55400
## 5 13063040303 45 33.42222 Census Tract 403.03 Clayton County Georgia 59300
## 6 13063040307 24 22.70833 Census Tract 403.07 Clayton County Georgia 69100
## 7 13063040308 74 26.32432 Census Tract 403.08 Clayton County Georgia 60500
## 8 13063040407 70 17.81429 Census Tract 404.07 Clayton County Georgia 89700
## 9 13063040408 51 26.47059 Census Tract 404.08 Clayton County Georgia 99200
## 10 13063040409 32 20.43750 Census Tract 404.09 Clayton County Georgia 88100
## hinc nroom unt_sng unt_mlt untstr_ p_singl p_multi cbd_dst in_atl
## 1 31524 5.6 614 397 1011 0.6073195 0.39268051 12908.51 0
## 2 36786 5.2 992 704 1696 0.5849057 0.41509434 15682.62 0
## 3 39194 4.5 843 1210 2064 0.4084302 0.58624031 15358.93 0
## 4 33190 4.9 1447 876 2323 0.6229014 0.37709858 11214.80 1
## 5 37236 5.4 2047 629 2730 0.7498168 0.23040293 11418.21 1
## 6 37064 6.2 1659 86 1772 0.9362302 0.04853273 15944.66 0
## 7 25159 4.7 1253 752 2038 0.6148184 0.36898921 11189.45 1
## 8 45768 5.5 1315 98 1465 0.8976109 0.06689420 14795.19 0
## 9 37224 5.6 1442 1408 2891 0.4987893 0.48702871 16444.02 0
## 10 42280 6.1 1880 221 2129 0.8830437 0.10380460 18062.68 0
## geometry
## 1 POLYGON ((674775.5 401071.4...
## 2 POLYGON ((672913.4 399171.9...
## 3 POLYGON ((673731.3 401102.2...
## 4 POLYGON ((679467.3 402730.3...
## 5 POLYGON ((681575.2 404460.5...
## 6 POLYGON ((680718 399789.9, ...
## 7 POLYGON ((678214.8 403283.3...
## 8 POLYGON ((681714.8 400107.7...
## 9 POLYGON ((682498.2 399520.2...
## 10 POLYGON ((686028.5 398774.5...
# summary() and str() function works exactly the same way
summary(sf.data)
## GEOID n walkscr tract
## 13063040202: 1 Min. : 3.00 Min. : 1.494 Census Tract 1 : 1
## 13063040203: 1 1st Qu.: 20.00 1st Qu.:14.197 Census Tract 10.01 : 1
## 13063040204: 1 Median : 34.00 Median :23.541 Census Tract 100.01: 1
## 13063040302: 1 Mean : 53.68 Mean :29.426 Census Tract 100.02: 1
## 13063040303: 1 3rd Qu.: 57.00 3rd Qu.:39.852 Census Tract 101.06: 1
## 13063040307: 1 Max. :2174.00 Max. :91.667 Census Tract 101.07: 1
## (Other) :495 (Other) :495
## county state mval hinc
## Clayton County: 46 Georgia:501 Min. : 53000 Min. : 9815
## Cobb County :119 1st Qu.: 102700 1st Qu.: 41481
## DeKalb County :141 Median : 182500 Median : 59981
## Fulton County :195 Mean : 230242 Mean : 67735
## 3rd Qu.: 322300 3rd Qu.: 85333
## Max. :1117200 Max. :200179
##
## nroom unt_sng unt_mlt untstr_
## Min. :3.00 Min. : 20 Min. : 0.0 Min. : 289
## 1st Qu.:4.90 1st Qu.: 794 1st Qu.: 152.0 1st Qu.:1591
## Median :5.70 Median :1345 Median : 574.0 Median :2129
## Mean :5.96 Mean :1462 Mean : 811.8 Mean :2296
## 3rd Qu.:7.00 3rd Qu.:1961 3rd Qu.:1211.0 3rd Qu.:2887
## Max. :9.00 Max. :5678 Max. :4207.0 Max. :6918
##
## p_singl p_multi cbd_dst in_atl
## Min. :0.02699 Min. :0.00000 Min. : 0 Min. :0.0000
## 1st Qu.:0.42914 1st Qu.:0.08032 1st Qu.: 8742 1st Qu.:0.0000
## Median :0.68703 Median :0.30144 Median :16455 Median :0.0000
## Mean :0.64728 Mean :0.34344 Mean :17086 Mean :0.3234
## 3rd Qu.:0.90680 3rd Qu.:0.56258 3rd Qu.:24119 3rd Qu.:1.0000
## Max. :1.00000 Max. :0.97301 Max. :43070 Max. :1.0000
##
## geometry
## POLYGON :501
## epsg:NA : 0
## +proj=tmer...: 0
##
##
##
##
str(sf.data)
## Classes 'sf' and 'data.frame': 501 obs. of 17 variables:
## $ GEOID : Factor w/ 501 levels "13063040202",..: 1 2 3 4 5 6 7 8 9 10 ...
## $ n : int 75 24 20 45 45 24 74 70 51 32 ...
## $ walkscr : num 18.8 26.2 37.4 31.7 33.4 ...
## $ tract : Factor w/ 501 levels "Census Tract 1",..: 381 382 383 384 385 386 387 388 389 390 ...
## $ county : Factor w/ 4 levels "Clayton County",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ state : Factor w/ 1 level "Georgia": 1 1 1 1 1 1 1 1 1 1 ...
## $ mval : num 98600 98200 105000 55400 59300 69100 60500 89700 99200 88100 ...
## $ hinc : num 31524 36786 39194 33190 37236 ...
## $ nroom : num 5.6 5.2 4.5 4.9 5.4 6.2 4.7 5.5 5.6 6.1 ...
## $ unt_sng : num 614 992 843 1447 2047 ...
## $ unt_mlt : num 397 704 1210 876 629 ...
## $ untstr_ : num 1011 1696 2064 2323 2730 ...
## $ p_singl : num 0.607 0.585 0.408 0.623 0.75 ...
## $ p_multi : num 0.393 0.415 0.586 0.377 0.23 ...
## $ cbd_dst : num 12909 15683 15359 11215 11418 ...
## $ in_atl : num 0 0 0 1 1 0 1 0 0 0 ...
## $ geometry:sfc_POLYGON of length 501; first list element: List of 1
## ..$ : num [1:52, 1:2] 674776 675100 675285 676275 676883 ...
## ..- attr(*, "class")= chr "XY" "POLYGON" "sfg"
## - attr(*, "sf_column")= chr "geometry"
## - attr(*, "agr")= Factor w/ 3 levels "constant","aggregate",..: NA NA NA NA NA NA NA NA NA NA ...
## ..- attr(*, "names")= chr "GEOID" "n" "walkscr" "tract" ...
# Let's take a look at what is stored in geometry column.
sf.data$geometry
## Geometry set for 501 features
## geometry type: POLYGON
## dimension: XY
## bbox: xmin: 636450.8 ymin: 371709.7 xmax: 713243.6 ymax: 464175.8
## epsg (SRID): NA
## proj4string: +proj=tmerc +lat_0=30 +lon_0=-84.16666666666667 +k=0.9999 +x_0=700000 +y_0=0 +ellps=GRS80 +units=m +no_defs
## First 5 geometries:
## POLYGON ((674775.5 401071.4, 675099.7 401184.7,...
## POLYGON ((672913.4 399171.9, 672915.7 399965.8,...
## POLYGON ((673731.3 401102.2, 674406.8 400989.6,...
## POLYGON ((679467.3 402730.3, 679909.1 403212.9,...
## POLYGON ((681575.2 404460.5, 682105.3 404468.9,...
# Going deeper into a cell of the data.frame..
sf.data$geometry[[1]]
## POLYGON ((674775.5 401071.4, 675099.7 401184.7, 675285.5 401273.4, 676274.5 401931, 676882.8 402396.9, 677143.3 402574, 677440.3 402708.5, 677775.2 402808, 677909.2 402832.8, 678249.3 402839.2, 678252.1 402817.4, 678330.9 402001.3, 678352.8 402001.1, 678362.5 401894, 678342.1 401894.2, 678488.4 401094.1, 678738.7 400068, 679290.3 398924.9, 679160.8 398863.1, 679246.7 398593.3, 679177.2 398315.6, 679175.3 398136.6, 679495.2 397816, 679535.4 397647, 679326.6 397813.3, 679121 397807.5, 679010.2 397908, 678942.8 398158.4, 678789.6 398313.6, 678404.9 398674.7, 678306.9 399468.8, 678149.7 399682.1, 677939.1 399773.8, 677726.5 399739.8, 677366.6 400230.1, 677296.4 400197, 677232.8 399499.7, 677110.5 399508.7, 676814.7 399578, 676675.2 399744.9, 676538.9 399809.3, 676096 399598.1, 675912.8 399417.2, 675600.2 399339.2, 675530.4 399411.7, 675233.2 399601.4, 675116.2 399735.9, 675010.9 400076.3, 674934.5 400493.5, 674798.7 400801.1, 674787 400861.2, 674775.5 401071.4))
Â
Because an sf object contains (1) geometry and (2) attributes (i.e., data.frame), plot works in two different ways.
# This generates multiple maps
plot(sf.data)
## Warning: plotting the first 10 out of 16 attributes; use max.plot = 16 to plot
## all
# This generates one map of hinc variable
plot(sf.data["walkscr"])
# Still you can do all the basic plots we have used in sf object.
plot(sf.data$walkscr, sf.data$nroom,
main = "Scatterplot Works the Same Way",
xlab = "Walk Score",
ylab = "Number of Rooms")
hist(sf.data$walkscr,
main = "Histogram Works the Same Way",
xlab = "Walk Score",
ylab = "Frequency")
Alternatively, you can use any one of multitude of packages designed for mapping. I personally like to use ‘tmap’ package.
‘tmap’ package has two modes that you can toggle back and forth; plot and view. You can set the mode using tmap_mode() function. Set to plot mode, ‘tmap’ will generate static map. If you set it to view mode, the package will generate an interactive map.
At minimum, ‘tmap’ requires two functions. The first function specifies which R object you want to map, and this is done using tm_shape() function. The second function specifies various aesthetic components of the map, and this is done using tm_polygons() for polygon shapefiles; tm_dots() for point shapefiles; and tm_lines() for line shapefiles. We have polygon shapefiles, so let use that.
# Grey map
tmap_mode('view') # This sets it to view mode. If you want to go back to static mode, do tmap_mode('plot')
## tmap mode set to interactive viewing
tm_shape(sf.data) + # Supply the name of sf object in tm_shape().
tm_polygons() # There is nothing in tm_polygons(), so it will be the most basic, grey map.
# Thematic map
tm_shape(sf.data) + # Supply the name of sf object in tm_shape().
tm_polygons(
id = "GEOID",
col = "walkscr") # col = argument determines the color of each polygon. I am using % White as my color.
You can add not only layers that are from the same data but also layers that comes from a different data. See below.
# Adding a point of the City Hall
# 1st data (the census data)
tm_shape(sf.data) +
tm_polygons(id = "GEOID", col = "walkscr") + # Map elements associated with the first data
tm_shape(cbd) + # 2nd data (5-mile buffer from Atlanta city hall)
tm_polygons(alpha = 0.7) # Map elements associated with the second data
There are other options as well, and you can stack different layers on one map like you do in ArcMap. If you want to just draw borders, use tm_borders().
# Setting the mode of tmap
tm_shape(sf.data) + # Supply the name of sf object in tm_shape().
tm_borders() # This will only draw boundaries
You can add other layers on top of the border, if you want. tm_bubbles() creates a circle for each unit with its size proportional to a variable (e.g., walkscore).
# Setting the mode of tmap
tm_shape(sf.data) + # Supply the name of sf object in tm_shape().
tm_borders(col = "blue",
alpha = 0.2) + # Change the color of the border to blue
tm_bubbles(size = "walkscr",
alpha = 0.3)
## Legend for symbol sizes not available in view mode.
For static maps, you can move legends too.
# Setting the mode of tmap
tmap_mode("plot")
## tmap mode set to plotting
tm_shape(sf.data) + # Supply the name of sf object in tm_shape().
tm_borders(col = "blue",
alpha = 0.2) + # Change the color of the border to blue
tm_bubbles(size = "walkscr",
alpha = 0.3) +
tm_legend(legend.position = c("left", "bottom"))
   Â
What is very handy about sf object is that we can apply all the subsetting techniques we learned (e.g., selecting certain rows or columns that meet some criteria) to an sf object, and it will not only work but also automatically apply it to geometries as well.
Select by Attributes: There is nothing that we need to learn to do this! We’ve learned it all!
# Setting map back to view mode.
tmap_mode('view')
## tmap mode set to interactive viewing
# Creating a subsetted data
sf.data.subset1 <- sf.data[sf.data$county == "Fulton County", ] # Return only those rows that are in Fulton
# See the result of the subsetting. This works exactly the same of normal data.frame.
sf.data.subset1
## Simple feature collection with 195 features and 16 fields
## geometry type: POLYGON
## dimension: XY
## bbox: xmin: 636450.8 ymin: 388416.6 xmax: 706367.7 ymax: 464175.8
## epsg (SRID): NA
## proj4string: +proj=tmerc +lat_0=30 +lon_0=-84.16666666666667 +k=0.9999 +x_0=700000 +y_0=0 +ellps=GRS80 +units=m +no_defs
## First 10 features:
## GEOID n walkscr tract county state mval
## 307 13121000100 27 51.55556 Census Tract 1 Fulton County Georgia 680600
## 308 13121000200 20 65.70000 Census Tract 2 Fulton County Georgia 548300
## 309 13121000400 11 72.00000 Census Tract 4 Fulton County Georgia 419300
## 310 13121000500 26 61.19231 Census Tract 5 Fulton County Georgia 343600
## 311 13121000600 12 80.91667 Census Tract 6 Fulton County Georgia 190300
## 312 13121000700 13 44.15385 Census Tract 7 Fulton County Georgia 258300
## 313 13121001001 6 81.33333 Census Tract 10.01 Fulton County Georgia 284600
## 314 13121001100 4 90.50000 Census Tract 11 Fulton County Georgia 293700
## 315 13121001201 6 89.16667 Census Tract 12.01 Fulton County Georgia 246800
## 316 13121001202 3 91.33333 Census Tract 12.02 Fulton County Georgia 227000
## hinc nroom unt_sng unt_mlt untstr_ p_singl p_multi cbd_dst in_atl
## 307 149450 7.4 1680 401 2098 0.80076263 0.1911344 4840.388 1
## 308 116094 6.7 1880 991 2871 0.65482410 0.3451759 4027.183 1
## 309 91857 4.8 283 902 1194 0.23701843 0.7554439 3755.205 1
## 310 85750 3.9 1199 2325 3524 0.34023837 0.6597616 4177.759 1
## 311 50969 3.4 368 2678 3046 0.12081418 0.8791858 3661.335 1
## 312 71214 5.5 351 67 418 0.83971292 0.1602871 3684.300 1
## 313 80132 3.5 136 1027 1163 0.11693895 0.8830610 2470.296 1
## 314 99205 3.5 216 3617 3833 0.05635273 0.9436473 3655.297 1
## 315 58603 3.6 296 2550 2869 0.10317184 0.8888114 2506.818 1
## 316 83063 3.0 142 3328 3470 0.04092219 0.9590778 2470.604 1
## geometry
## 307 POLYGON ((681417.9 421943.5...
## 308 POLYGON ((680783.2 421461.6...
## 309 POLYGON ((679545.4 420877.8...
## 310 POLYGON ((678314.2 420537.6...
## 311 POLYGON ((676981.4 419617.1...
## 312 POLYGON ((675397.2 419828.9...
## 313 POLYGON ((678509 419814.7, ...
## 314 POLYGON ((679519 419633.4, ...
## 315 POLYGON ((679945.3 418412.7...
## 316 POLYGON ((679516.5 419342.9...
# Plot it
tm_shape(sf.data.subset1) +
tm_polygons(col = "walkscr")
As you can see, subsetting technique we learned so far NOT ONLY FOR THE DATA.FRAME PART BUT ALSO ON GEOMETRIES. Let’s add all non-Fulton County with just the borders to visualize rest of the dataset.
tm_shape(sf.data.subset1) + # First data
tm_polygons(col = "walkscr") + # Map elements of the first data
tm_shape(sf.data) + # Second data
tm_borders(alpha = 0.5) # Map elements of the second data.
sf package works well with ‘tidyverse’ package and the %>% operator. For those who learned how to use %>% operator, the following code may be more handy and clean because it allows you to do data manipulation on the fly which saves you from creating unnecessary objects and clutter your R environment.
# tidyverse way
sf.data %>%
filter(walkscr > 20) %>%
tm_shape(.) + # If you want to use static map, add the following as another argument in tm_shape: bbox = st_bbox(sf.data)
tm_polygons(col = "walkscr") +
tm_shape(sf.data) +
tm_borders(alpha = 0.5)
Select by Location: As you’ve learned in ArcMap, it is possible to subset your data based on geographic relationships. Here we use sf.data and cbd to demonstrate a few different ways to subset by location.
# Visualization
tm_shape(sf.data) +
tm_polygons() +
tm_shape(cbd) +
tm_borders(col = "red")
# Create subset data
sf.data.cbd <- sf.data[cbd,,op = st_intersects] # [sf object, leave this one empty, operation]
# Visualization for sanity check again
# 1st layer
tm_shape(sf.data) +
tm_polygons(alpha = 0.5) +
# 2nd layer
tm_shape(sf.data.cbd) +
tm_polygons(col = "blue") +
# 3rd layer
tm_shape(cbd) +
tm_borders(col = "red",
lwd = 3)
Now that we tried one operation (i.e., intersects), let’s try other commonly used ones.
# Creating multiple objects with different operations
intersects <- sf.data[cbd,,op = st_intersects]
disjoint <- sf.data[cbd,,op = st_disjoint]
within <- sf.data[cbd,,op = st_within]
within_distance <- sf.data[cbd, , op = st_is_within_distance, dist = 1600*5]
# Creating a static map for each of them (NO NEED FOR YOU TO UNDERSTAND THESE CODES)
intersects.map <- tm_shape(intersects, bbox = st_bbox(sf.data)) +
tm_polygons(col = "blue") +
tm_shape(sf.data) +
tm_borders(alpha = 0.5) + tm_shape(cbd) +
tm_borders(col = "red")
disjoint.map <- tm_shape(disjoint, bbox = st_bbox(sf.data)) +
tm_polygons(col = "blue") +
tm_shape(sf.data) +
tm_borders(alpha = 0.5) +
tm_shape(cbd) +
tm_borders(col = "red")
within.map <- tm_shape(within, bbox = st_bbox(sf.data)) +
tm_polygons(col = "blue") +
tm_shape(sf.data)+
tm_borders(alpha = 0.5) +
tm_shape(cbd) +
tm_borders(col = "red")
within_distance.map <- tm_shape(within_distance, bbox = st_bbox(sf.data)) +
tm_polygons(col = "blue") +
tm_shape(sf.data)+
tm_borders(alpha = 0.5) +
tm_shape(cbd) +
tm_borders(col = "red")
# Putting those maps altogether
tmap_mode('plot')
## tmap mode set to plotting
tmap_arrange(intersects.map, disjoint.map, within.map, within_distance.map)