class: center, middle, inverse, title-slide # Introduction to leaflet mapping ## Data Visualisation in R: Maps! ### Dr. Laurie Baker ### Bates College adapted from Data Science Campus ### 2020/04/09 (updated: 2021-11-27) --- layout: false class: inverse center middle text-white .font200[Introduction to leaflet] --- # About me .pull-left[ .center[ <img style="border-radius: 50%;" src="images/laurie_baker.jpg" width="300px"/> .font150[**Dr. Laurie Baker**] Visiting Assistant Professor of Digital and Computational Studies, Bates College ]] .pull-right[ ### Education <svg viewBox="0 0 640 512" style="height:1em;position:relative;display:inline-block;top:.1em;" xmlns="http://www.w3.org/2000/svg"> <path d="M622.34 153.2L343.4 67.5c-15.2-4.67-31.6-4.67-46.79 0L17.66 153.2c-23.54 7.23-23.54 38.36 0 45.59l48.63 14.94c-10.67 13.19-17.23 29.28-17.88 46.9C38.78 266.15 32 276.11 32 288c0 10.78 5.68 19.85 13.86 25.65L20.33 428.53C18.11 438.52 25.71 448 35.94 448h56.11c10.24 0 17.84-9.48 15.62-19.47L82.14 313.65C90.32 307.85 96 298.78 96 288c0-11.57-6.47-21.25-15.66-26.87.76-15.02 8.44-28.3 20.69-36.72L296.6 284.5c9.06 2.78 26.44 6.25 46.79 0l278.95-85.7c23.55-7.24 23.55-38.36 0-45.6zM352.79 315.09c-28.53 8.76-52.84 3.92-65.59 0l-145.02-44.55L128 384c0 35.35 85.96 64 192 64s192-28.65 192-64l-14.18-113.47-145.03 44.56z"></path></svg> BSc and MSc, Marine Biology <svg viewBox="0 0 640 512" style="height:1em;position:relative;display:inline-block;top:.1em;" xmlns="http://www.w3.org/2000/svg"> <path d="M622.34 153.2L343.4 67.5c-15.2-4.67-31.6-4.67-46.79 0L17.66 153.2c-23.54 7.23-23.54 38.36 0 45.59l48.63 14.94c-10.67 13.19-17.23 29.28-17.88 46.9C38.78 266.15 32 276.11 32 288c0 10.78 5.68 19.85 13.86 25.65L20.33 428.53C18.11 438.52 25.71 448 35.94 448h56.11c10.24 0 17.84-9.48 15.62-19.47L82.14 313.65C90.32 307.85 96 298.78 96 288c0-11.57-6.47-21.25-15.66-26.87.76-15.02 8.44-28.3 20.69-36.72L296.6 284.5c9.06 2.78 26.44 6.25 46.79 0l278.95-85.7c23.55-7.24 23.55-38.36 0-45.6zM352.79 315.09c-28.53 8.76-52.84 3.92-65.59 0l-145.02-44.55L128 384c0 35.35 85.96 64 192 64s192-28.65 192-64l-14.18-113.47-145.03 44.56z"></path></svg> PhD, Epidemiology <svg viewBox="0 0 512 512" style="height:1em;position:relative;display:inline-block;top:.1em;" xmlns="http://www.w3.org/2000/svg"> <path d="M458.622 255.92l45.985-45.005c13.708-12.977 7.316-36.039-10.664-40.339l-62.65-15.99 17.661-62.015c4.991-17.838-11.829-34.663-29.661-29.671l-61.994 17.667-15.984-62.671C337.085.197 313.765-6.276 300.99 7.228L256 53.57 211.011 7.229c-12.63-13.351-36.047-7.234-40.325 10.668l-15.984 62.671-61.995-17.667C74.87 57.907 58.056 74.738 63.046 92.572l17.661 62.015-62.65 15.99C.069 174.878-6.31 197.944 7.392 210.915l45.985 45.005-45.985 45.004c-13.708 12.977-7.316 36.039 10.664 40.339l62.65 15.99-17.661 62.015c-4.991 17.838 11.829 34.663 29.661 29.671l61.994-17.667 15.984 62.671c4.439 18.575 27.696 24.018 40.325 10.668L256 458.61l44.989 46.001c12.5 13.488 35.987 7.486 40.325-10.668l15.984-62.671 61.994 17.667c17.836 4.994 34.651-11.837 29.661-29.671l-17.661-62.015 62.65-15.99c17.987-4.302 24.366-27.367 10.664-40.339l-45.984-45.004z"></path></svg> Certified Tidyverse Instructor, RStudio ### Research Interests <svg viewBox="0 0 512 512" style="height:1em;position:relative;display:inline-block;top:.1em;" xmlns="http://www.w3.org/2000/svg"> <path d="M201.5 174.8l55.7 55.8c3.1 3.1 3.1 8.2 0 11.3l-11.3 11.3c-3.1 3.1-8.2 3.1-11.3 0l-55.7-55.8-45.3 45.3 55.8 55.8c3.1 3.1 3.1 8.2 0 11.3l-11.3 11.3c-3.1 3.1-8.2 3.1-11.3 0L111 265.2l-26.4 26.4c-17.3 17.3-25.6 41.1-23 65.4l7.1 63.6L2.3 487c-3.1 3.1-3.1 8.2 0 11.3l11.3 11.3c3.1 3.1 8.2 3.1 11.3 0l66.3-66.3 63.6 7.1c23.9 2.6 47.9-5.4 65.4-23l181.9-181.9-135.7-135.7-64.9 65zm308.2-93.3L430.5 2.3c-3.1-3.1-8.2-3.1-11.3 0l-11.3 11.3c-3.1 3.1-3.1 8.2 0 11.3l28.3 28.3-45.3 45.3-56.6-56.6-17-17c-3.1-3.1-8.2-3.1-11.3 0l-33.9 33.9c-3.1 3.1-3.1 8.2 0 11.3l17 17L424.8 223l17 17c3.1 3.1 8.2 3.1 11.3 0l33.9-34c3.1-3.1 3.1-8.2 0-11.3l-73.5-73.5 45.3-45.3 28.3 28.3c3.1 3.1 8.2 3.1 11.3 0l11.3-11.3c3.1-3.2 3.1-8.2 0-11.4z"></path></svg> Public Health, <svg viewBox="0 0 576 512" style="height:1em;position:relative;display:inline-block;top:.1em;" xmlns="http://www.w3.org/2000/svg"> <path d="M327.1 96c-89.97 0-168.54 54.77-212.27 101.63L27.5 131.58c-12.13-9.18-30.24.6-27.14 14.66L24.54 256 .35 365.77c-3.1 14.06 15.01 23.83 27.14 14.66l87.33-66.05C158.55 361.23 237.13 416 327.1 416 464.56 416 576 288 576 256S464.56 96 327.1 96zm87.43 184c-13.25 0-24-10.75-24-24 0-13.26 10.75-24 24-24 13.26 0 24 10.74 24 24 0 13.25-10.75 24-24 24z"></path></svg> Ecology, <svg viewBox="0 0 576 512" style="height:1em;position:relative;display:inline-block;top:.1em;" xmlns="http://www.w3.org/2000/svg"> <path d="M528 0H48C21.5 0 0 21.5 0 48v320c0 26.5 21.5 48 48 48h192l-16 48h-72c-13.3 0-24 10.7-24 24s10.7 24 24 24h272c13.3 0 24-10.7 24-24s-10.7-24-24-24h-72l-16-48h192c26.5 0 48-21.5 48-48V48c0-26.5-21.5-48-48-48zm-16 352H64V64h448v288z"></path></svg> Data Science ] .center[ [<svg viewBox="0 0 512 512" style="height:1em;position:relative;display:inline-block;top:.1em;" xmlns="http://www.w3.org/2000/svg"> <path d="M326.612 185.391c59.747 59.809 58.927 155.698.36 214.59-.11.12-.24.25-.36.37l-67.2 67.2c-59.27 59.27-155.699 59.262-214.96 0-59.27-59.26-59.27-155.7 0-214.96l37.106-37.106c9.84-9.84 26.786-3.3 27.294 10.606.648 17.722 3.826 35.527 9.69 52.721 1.986 5.822.567 12.262-3.783 16.612l-13.087 13.087c-28.026 28.026-28.905 73.66-1.155 101.96 28.024 28.579 74.086 28.749 102.325.51l67.2-67.19c28.191-28.191 28.073-73.757 0-101.83-3.701-3.694-7.429-6.564-10.341-8.569a16.037 16.037 0 0 1-6.947-12.606c-.396-10.567 3.348-21.456 11.698-29.806l21.054-21.055c5.521-5.521 14.182-6.199 20.584-1.731a152.482 152.482 0 0 1 20.522 17.197zM467.547 44.449c-59.261-59.262-155.69-59.27-214.96 0l-67.2 67.2c-.12.12-.25.25-.36.37-58.566 58.892-59.387 154.781.36 214.59a152.454 152.454 0 0 0 20.521 17.196c6.402 4.468 15.064 3.789 20.584-1.731l21.054-21.055c8.35-8.35 12.094-19.239 11.698-29.806a16.037 16.037 0 0 0-6.947-12.606c-2.912-2.005-6.64-4.875-10.341-8.569-28.073-28.073-28.191-73.639 0-101.83l67.2-67.19c28.239-28.239 74.3-28.069 102.325.51 27.75 28.3 26.872 73.934-1.155 101.96l-13.087 13.087c-4.35 4.35-5.769 10.79-3.783 16.612 5.864 17.194 9.042 34.999 9.69 52.721.509 13.906 17.454 20.446 27.294 10.606l37.106-37.106c59.271-59.259 59.271-155.699.001-214.959z"></path></svg> lauriebaker.rbind.io](https://lauriebaker.rbind.io) [<svg viewBox="0 0 512 512" style="height:1em;position:relative;display:inline-block;top:.1em;" xmlns="http://www.w3.org/2000/svg"> <path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"></path></svg> @llbaker1707](https://twitter.com/llbaker1707) [<svg viewBox="0 0 496 512" style="position:relative;display:inline-block;top:.1em;height:1em;" xmlns="http://www.w3.org/2000/svg"> <path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"></path></svg> @laurielbaker](https://github.com/laurielbaker) ] --- layout: true # What we'll cover today. --- - Intro to the `sf` package -- - Building a map using `ggplot2` -- - Coordinate Systems and geospatial objects in R -- - Building interactive maps using `leaflet`. --- layout: true # Packages for today's adventure --- ```r library(tidyverse) ## For plotting and data wrangling. library(leaflet) ## For leaflet interactive maps library(sf) ## For spatial data library(RColorBrewer) ## For colour palettes library(htmltools) ## For html library(leafsync) ## For placing plots side by side library(kableExtra) ## Table output (in slides) ``` --- layout: false class: inverse center middle text-white .font200[Introduction to the sf package] --- layout: false # The sf package * Package for geospatial data manipulation and analysis that works with features * **points** (POINT, MULTIPOINT) * **lines** (LINESTRING, MULTILINESTRING) * **polygons** (POLYGON, MULTIPOLYGON) <img src="images/spatial_data_types.jpg" title="Diagram showing series of points (GPS locations), lines (roads), and polygons (e.g. countries and regions)" alt="Diagram showing series of points (GPS locations), lines (roads), and polygons (e.g. countries and regions)" width="100%" /> --- layout: true # Births in North Carolina --- * We will use the North Carolina (`nc`) data from the `sf` package. -- * Let's load in the data for North Carolina using the function `st_read`. -- ```r nc_df <- st_read(system.file("shape/nc.shp", package="sf")) ``` ``` ## Reading layer `nc' from data source ## `/Library/Frameworks/R.framework/Versions/4.1/Resources/library/sf/shape/nc.shp' ## using driver `ESRI Shapefile' ## Simple feature collection with 100 features and 14 fields ## Geometry type: MULTIPOLYGON ## Dimension: XY ## Bounding box: xmin: -84.32385 ymin: 33.88199 xmax: -75.45698 ymax: 36.58965 ## Geodetic CRS: NAD27 ``` * `st` = spatial type and `.shp` is a common shape file format (e.g. GIS). -- --- layout: true # Rename the columns and view the data --- * Number of births for counties in North Carolina in 1974 * Rename our columns to country, births, and geometry. ```r nc <- nc_df %>% select("NAME", "BIR74", "BIR79", "geometry") %>% rename("county" = "NAME", "births1974" = "BIR74", "births1979" = "BIR79") ``` --- layout: true # Let's inspect the data * Let's load in the data for North Carolina (nc) ```r head(nc) ``` <div class="kable-table"> <table> <thead> <tr> <th style="text-align:left;"> county </th> <th style="text-align:right;"> births1974 </th> <th style="text-align:right;"> births1979 </th> <th style="text-align:left;"> geometry </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> Ashe </td> <td style="text-align:right;"> 1091 </td> <td style="text-align:right;"> 1364 </td> <td style="text-align:left;"> MULTIPOLYGON (((-81.47276 3... </td> </tr> <tr> <td style="text-align:left;"> Alleghany </td> <td style="text-align:right;"> 487 </td> <td style="text-align:right;"> 542 </td> <td style="text-align:left;"> MULTIPOLYGON (((-81.23989 3... </td> </tr> <tr> <td style="text-align:left;"> Surry </td> <td style="text-align:right;"> 3188 </td> <td style="text-align:right;"> 3616 </td> <td style="text-align:left;"> MULTIPOLYGON (((-80.45634 3... </td> </tr> <tr> <td style="text-align:left;"> Currituck </td> <td style="text-align:right;"> 508 </td> <td style="text-align:right;"> 830 </td> <td style="text-align:left;"> MULTIPOLYGON (((-76.00897 3... </td> </tr> <tr> <td style="text-align:left;"> Northampton </td> <td style="text-align:right;"> 1421 </td> <td style="text-align:right;"> 1606 </td> <td style="text-align:left;"> MULTIPOLYGON (((-77.21767 3... </td> </tr> <tr> <td style="text-align:left;"> Hertford </td> <td style="text-align:right;"> 1452 </td> <td style="text-align:right;"> 1838 </td> <td style="text-align:left;"> MULTIPOLYGON (((-76.74506 3... </td> </tr> </tbody> </table> </div> --- layout: true # And inspect the structure ```r str(nc) ``` ``` ## Classes 'sf' and 'data.frame': 100 obs. of 4 variables: ## $ county : chr "Ashe" "Alleghany" "Surry" "Currituck" ... ## $ births1974: num 1091 487 3188 508 1421 ... ## $ births1979: num 1364 542 3616 830 1606 ... ## $ geometry :sfc_MULTIPOLYGON of length 100; first list element: List of 1 ## ..$ :List of 1 ## .. ..$ : num [1:27, 1:2] -81.5 -81.5 -81.6 -81.6 -81.7 ... ## ..- attr(*, "class")= chr [1:3] "XY" "MULTIPOLYGON" "sfg" ## - attr(*, "sf_column")= chr "geometry" ## - attr(*, "agr")= Factor w/ 3 levels "constant","aggregate",..: NA NA NA ## ..- attr(*, "names")= chr [1:3] "county" "births1974" "births1979" ``` --- layout: false class: inverse center middle text-white .font200[Plotting a map with ggplot2] --- layout: true # Building a map in ggplot2 --- .left-code[ ```r *ggplot(nc) ``` * .hlb[Data] * Geom * Aesthetics * Labels * Scales ] .right-plot[ <img src="leaflet_slides2_files/figure-html/first-map1a-1.png" title="Empty plotting area" alt="Empty plotting area" width="95%" /> ] --- .left-code[ ```r ggplot(nc) + * geom_sf() ``` * Data * .hlb[Geom] * Aesthetics * Labels * Scales ] .right-plot[ <img src="leaflet_slides2_files/figure-html/first-map1b-1.png" title="Map of North Carolina showing border of counties." alt="Map of North Carolina showing border of counties." width="95%" /> ] --- .left-code[ ```r ggplot(nc) + * geom_sf(aes(fill = births1974)) ``` * Data * Geom * .hlb[Aesthetics] * Labels * Scales ] .right-plot[ <img src="leaflet_slides2_files/figure-html/first-map1c-1.png" title="Map of North Carolina with administrative regions filled by number of births in North Carolina counties from 1974-78." alt="Map of North Carolina with administrative regions filled by number of births in North Carolina counties from 1974-78." width="95%" /> ] --- .left-code[ ```r ggplot(nc) + geom_sf(aes(fill = births1974)) + * labs(title = "Births per county in 1974-1978", * x = "Longitude", * y = "Latitude", * fill = "# Births") ``` * Data * Geom * Aesthetics * .hlb[Labels] * Scales ] .right-plot[ <img src="leaflet_slides2_files/figure-html/first-map1d-1.png" title="Map updated to include a title, x and y axis labels, and a legend. Map of North Carolina with administrative regions filled by number of births in North Carolina counties from 1974-78. On the x axis, longitude, on the y axis latitude, and a legend indicating the number of suddent infant death cases." alt="Map updated to include a title, x and y axis labels, and a legend. Map of North Carolina with administrative regions filled by number of births in North Carolina counties from 1974-78. On the x axis, longitude, on the y axis latitude, and a legend indicating the number of suddent infant death cases." width="95%" /> ] --- .left-code[ ```r ggplot(nc) + geom_sf(aes(fill = births1974)) + labs(title = "Births per county in 1974-1978", x = "Longitude", y = "Latitude", fill = "# births") + * scale_y_continuous(breaks = 34:36) ``` * Data * Geom * Aesthetics * Labels * .hlb[Scales] ] .right-plot[ <img src="leaflet_slides2_files/figure-html/first-map1e-1.png" title="Map updated so that the y axis has breaks at 34, 35, and 36 degrees latitude. Map of North Carolina with administrative regions filled by number of births in North Carolina counties from 1974-78. On the x axis, longitude, on the y axis latitude, and a legend indicating the number of suddent infant death cases." alt="Map updated so that the y axis has breaks at 34, 35, and 36 degrees latitude. Map of North Carolina with administrative regions filled by number of births in North Carolina counties from 1974-78. On the x axis, longitude, on the y axis latitude, and a legend indicating the number of suddent infant death cases." width="95%" /> ] --- layout: true # Coordinate reference system --- * Every location on earth is specified by a longitude and latitude. -- * The Coordinate Reference system (CRS) determines how the data will be projected onto a map. -- <figure> <img src="images/map_projections.gif" width="850px"> <figcaption>[Projection Transitions](https://bl.ocks.org/mbostock/raw/3711652/) by Mick Bostock </figcaption> </figure> --- layout: true # Coordinate reference system can skew true size --- <img src="images/Kenya_true_size.PNG" title="Map of the world showing Kenya overlaid on Greenland. The map demonstrates how coordinate reference systems skew our perception of how big a country is" alt="Map of the world showing Kenya overlaid on Greenland. The map demonstrates how coordinate reference systems skew our perception of how big a country is" width="70%" /> [The True Size Of: thetruesize.com](https://thetruesize.com/#?borders=1~!MTczMDY3NDE.MTE4OTczMjc*MjU3NDY1NzA(MzkyMTU3MA~!KE*OTYxNTIxNw.MTY3MDYyNzg) --- layout: true # Checking the coordinate reference system --- * We can check the CRS using `st_crs`: ```r st_crs(nc) ``` ``` ## Coordinate Reference System: ## User input: NAD27 ## wkt: ## GEOGCRS["NAD27", ## DATUM["North American Datum 1927", ## ELLIPSOID["Clarke 1866",6378206.4,294.978698213898, ## LENGTHUNIT["metre",1]]], ## PRIMEM["Greenwich",0, ## ANGLEUNIT["degree",0.0174532925199433]], ## CS[ellipsoidal,2], ## AXIS["latitude",north, ## ORDER[1], ## ANGLEUNIT["degree",0.0174532925199433]], ## AXIS["longitude",east, ## ORDER[2], ## ANGLEUNIT["degree",0.0174532925199433]], ## ID["EPSG",4267]] ``` * The CRS is specified in the attributes `epsg` and `proj4string`. --- layout: true # Transforming coordinate reference system --- * You can transform a coordinate reference system using the `st_transform()`. -- * But what is a sensible coordinate reference system to assign? -- * If we are making a plot using leaflet we can use: EPSG 4326. ```r nc <- st_transform(nc, "+init=epsg:4326") st_crs(nc) ``` ``` ## Coordinate Reference System: ## User input: +init=epsg:4326 ## wkt: ## GEOGCRS["unknown", ## DATUM["World Geodetic System 1984", ## ELLIPSOID["WGS 84",6378137,298.257223563, ## LENGTHUNIT["metre",1]], ## ID["EPSG",6326]], ## PRIMEM["Greenwich",0, ## ANGLEUNIT["degree",0.0174532925199433], ## ID["EPSG",8901]], ## CS[ellipsoidal,2], ## AXIS["longitude",east, ## ORDER[1], ## ANGLEUNIT["degree",0.0174532925199433, ## ID["EPSG",9122]]], ## AXIS["latitude",north, ## ORDER[2], ## ANGLEUNIT["degree",0.0174532925199433, ## ID["EPSG",9122]]]] ``` --- layout: true # Introduction to leaflet mapping --- * Leaflet is one of the most popular open-source JavaScript libraries for interactive maps * Like `ggplot2` it is built in layers on top of a base map --- layout: true # Our first leaflet map --- .left-code[ * Every plot starts with `leaflet()` ```r leaflet(data = nc) ``` ] .right-plot[
] --- .left-code[ * Layers are added using `%>%` ```r leaflet(data = nc) %>% * addTiles() ``` ] .right-plot[
] -- N.B. Layers are added with `%>%` in `leaflet` and `+` in `ggplot`. `%>%` also is used in the `tidyverse` packages. --- .left-code[ * We can set the view using `setView()` ```r leaflet(data = nc) %>% addTiles() %>% * setView(lng = -80, * lat = 34.5, * zoom = 5) ``` * **Your Turn**: Try setting lng to 38 and lat to 1. Try setting different values between 0 and 10 for the zoom. ] .right-plot[
] --- .left-code[ * We can set the view using `setView()` ```r leaflet(data = nc) %>% addTiles() %>% * setView(lng = 38, * lat = 1, * zoom = 6) ``` ] .right-plot[
] --- layout: true # Our first leaflet map --- .left-code[ * `addProviderTiles` give different base maps ```r leaflet(data = nc) %>% addProviderTiles(providers$Stamen.Terrain) %>% setView(lng = -80, lat = 34.5, zoom = 5) ``` * **Your Turn**: Choose a different provider tile: `providers$` + `Tab`. ] .right-plot[
N.B. The different provider tiles come with different licensing and some require an API. ] --- .left-code[ * Add polygons using `addPolygons()` ```r leaflet(data = nc) %>% addProviderTiles(providers$Stamen.Terrain) %>% setView(lng = -80, lat = 34.5, zoom = 5) %>% * addPolygons() ``` ] .right-plot[
] --- layout: true # Creating a colour palette --- <img src="images/ColorBrewer_Ex.PNG" title="Map of U.S. Counties showing green blue colour scheme" alt="Map of U.S. Counties showing green blue colour scheme" width="550" style="display: block; margin: auto;" /> * What type of variables are we showing (numerical, categorical)? -- * What story are we telling with our data? -- * Choose your colours: [ColorBrewer2.org](https://colorbrewer2.org/#type=sequential&scheme=BuGn&n=3) and https://www.colorcodepicker.com/ --- layout: true # Creating a colour palette --- * `RColorBrewer` includes **sequential** colour palettes (e.g. number of people). ```r display.brewer.all(type = "seq") ``` <img src="leaflet_slides2_files/figure-html/pal-sequential-1.png" title="Diagram showing sequential palettes available in RColorBrewer including Orange to Red and more" alt="Diagram showing sequential palettes available in RColorBrewer including Orange to Red and more" width="70%" /> --- layout: true # Creating a colour palette --- * `RColorBrewer` includes **diverging** colour palettes (e.g. to show distinct categories). ```r display.brewer.all(type = "div") ``` <img src="leaflet_slides2_files/figure-html/pal-diverging-1.png" title="Diagram showing sequential palettes available in RColorBrewer including Spectral and Red to Blue" alt="Diagram showing sequential palettes available in RColorBrewer including Spectral and Red to Blue" width="70%" /> --- layout: true # Creating a colour palette --- * First we will define the colour palette and bins for the plot. ```r summary(nc$births1974) ``` ``` ## Min. 1st Qu. Median Mean 3rd Qu. Max. ## 248 1077 2180 3300 3936 21588 ``` ```r summary(nc$births1979) ``` ``` ## Min. 1st Qu. Median Mean 3rd Qu. Max. ## 319 1336 2636 4224 4889 30757 ``` ```r bins <- seq(0, 35000, 5000) ``` --- * Then we can define the colours for the palette: ```r pal74 <- colorBin("OrRd", domain = nc$births1974, bins = bins) pal79 <- colorBin("OrRd", domain = nc$births1979, bins = bins) ``` --- .left-code[ * Customizing `addPolygons()` ```r leaflet(data = nc) %>% addProviderTiles(providers$Esri.OceanBasemap) %>% setView(lng = -80, lat = 34.5, zoom = 6) %>% addPolygons( fillColor = ~pal74(nc$births1974), * fillOpacity = 0.7, * color = "white", * opacity = 1, * weight = 2 ) ``` ] .right-plot[
] --- .left-code[ * Customising `addPolygons()` ```r leaflet(data = nc) %>% addProviderTiles(providers$Esri.OceanBasemap) %>% setView(lng = -80, lat = 34.5, zoom = 6) %>% addPolygons( * fillColor = ~pal74(nc$births1974), * fillOpacity = 1, * color = "blue", * opacity = 0.7, * weight = 1 ) ``` ] .right-plot[
* **Your Turn** Try changing the `color`, `opacity`, and `weight` ] --- layout: true # What can you customise in addPolygons() --- ```r ?addPolygons() ``` * `color:` stroke color * `weight:` stroke width in pixels * `opacity:` stroke opacity * `fillColor:` fill color * `fillOpacity:` fill opacity -- * `highlightOptions:` Options for highlighting the shape on mouse over. --- .left-code[ * Let's assign our plot to an object. ```r *m1 <- leaflet(data = nc) %>% addProviderTiles(providers$Stamen.Terrain) %>% setView(lng = -80, lat = 34.5, zoom = 6) m1 %>% addPolygons( fillColor = ~pal74(nc$births1974), fillOpacity = 0.7, opacity = 1, color = "white", weight = 2) ``` ] .right-plot[
] --- .left-code[ * Let's add some `highlightOptions` ```r m1 %>% addPolygons( fillColor = ~pal74(nc$births1974), fillOpacity = 0.7, color = "white", opacity = 1, weight = 2, * highlight = highlightOptions( * weight = 3, * color = "blue", * fillOpacity = 1, * bringToFront = TRUE)) ``` ] .right-plot[
] --- layout: true # Let's add some labels! --- `sprintf`: returns a character vector containing a formatted combination of text and variable values. ```r labels <- sprintf("<strong>%s</strong><br/>%g births", nc$county, nc$births1974) %>% lapply(htmltools::HTML) head(labels, 1) ``` ``` ## [[1]] ## <strong>Ashe</strong><br/>1091 births ``` -- html - markup language for the web * `<strong>` = bold; `<br/>` = new line -- PHP - Hypertext Preprocessor * `%s` = place holder for a character string; `%g` = general format place holder for a number --- .left-code[ * Let's add some labels ```r (m1 <- m1 %>% addPolygons(data = nc, fillColor = ~pal74(nc$births1974), fillOpacity = 0.7, color = "white", opacity = 1, weight = 2, highlight = highlightOptions( weight = 3, color = "blue", fillOpacity = 1, bringToFront = TRUE), * label = labels)) ``` ] .right-plot[
] --- .left-code[ * Let's add a legend ```r m1 <- m1 %>% * addLegend( * position = "bottomright", * pal = pal74, * values = ~nc$births1974, * title = "Births by county in 1974", * opacity = 1) m1 ``` ] .right-plot[
] --- layout: true # Let's create a second map --- * Let's create a second map of births in 1979. * First we'll need to create a new set of labels ```r labels79 <- sprintf( "<strong>%s</strong><br/>%g births", nc$county, nc$births1974 ) %>% lapply(htmltools::HTML) ``` * **Your Turn** Using `names(nc)` to check the column names, change `nc$births1974` to the column which corresponds to number of births in 1979. --- layout: true # Let's create a second map --- ```r m2 <- leaflet(data = nc) %>% addProviderTiles(providers$Stamen.Terrain) %>% setView(lng = -80, lat = 34.5, zoom = 6) %>% addPolygons( fillColor = ~pal79(nc$births1979), fillOpacity = 0.7, color = "white", opacity = 1, weight = 2, highlight = highlightOptions( weight = 3, color = "blue", fillOpacity = 1, bringToFront = TRUE), label = labels79) ``` --- ```r m2 <- m2 %>% addLegend( position = "bottomright", pal = pal79, values = ~nc$births1979, title = "Births by country in 1979", opacity = 1) ``` --- ```r m2 ```
--- layout: true # Placing two maps side by side --- ```r leafsync::sync(m1, m2, ncol = 2, sync = "all") ```
--- layout: true # Leaflet maps with points --- ```r head(work) ``` <div class="kable-table"> <table> <thead> <tr> <th style="text-align:left;"> location </th> <th style="text-align:left;"> institute </th> <th style="text-align:left;"> work </th> <th style="text-align:right;"> lat </th> <th style="text-align:right;"> lon </th> <th style="text-align:left;"> icon </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> Valparaíso, Chile </td> <td style="text-align:left;"> Instituto de Fomento Pesquero </td> <td style="text-align:left;"> Chilean Pink Cusk Eel </td> <td style="text-align:right;"> -33.0472 </td> <td style="text-align:right;"> -71.6127 </td> <td style="text-align:left;"> fish </td> </tr> <tr> <td style="text-align:left;"> Curitiba, Brasil </td> <td style="text-align:left;"> Universidade Federal do Paraná </td> <td style="text-align:left;"> Fox rabies </td> <td style="text-align:right;"> -25.4290 </td> <td style="text-align:right;"> -49.2671 </td> <td style="text-align:left;"> disease </td> </tr> <tr> <td style="text-align:left;"> Sable Island, Nova Scotia </td> <td style="text-align:left;"> Dalhousie University </td> <td style="text-align:left;"> Grey seals </td> <td style="text-align:right;"> 43.9337 </td> <td style="text-align:right;"> -59.9149 </td> <td style="text-align:left;"> gps </td> </tr> <tr> <td style="text-align:left;"> Greifswald, Germany </td> <td style="text-align:left;"> Friedrich Loeffler Institut </td> <td style="text-align:left;"> Fox rabies </td> <td style="text-align:right;"> 54.0865 </td> <td style="text-align:right;"> 13.3923 </td> <td style="text-align:left;"> disease </td> </tr> <tr> <td style="text-align:left;"> Arusha, Tanzania </td> <td style="text-align:left;"> Nelson Mandela African Institute of Science and Technology </td> <td style="text-align:left;"> Teaching </td> <td style="text-align:right;"> -3.3995 </td> <td style="text-align:right;"> 36.7968 </td> <td style="text-align:left;"> training </td> </tr> <tr> <td style="text-align:left;"> Kigali, Rwanda </td> <td style="text-align:left;"> National Institute of Statistics Rwanda </td> <td style="text-align:left;"> Teaching </td> <td style="text-align:right;"> -1.9415 </td> <td style="text-align:right;"> 30.0574 </td> <td style="text-align:left;"> training </td> </tr> </tbody> </table> </div> --- layout: true # Leaflet map with points --- .left-code[ ```r leaflet(work) %>% addProviderTiles(providers$Stamen.Watercolor) %>% addProviderTiles(providers$Stamen.TerrainLabels) %>% addCircleMarkers(~lon, ~lat) ``` * **Your Turn** What else can you change about addCircleMarkers? Hint: Type `??addControl` Try adding: `clusterOptions = markerClusterOptions()` to your map. ] .right-plot[
] --- .left-code[ ```r leaflet(work) %>% addProviderTiles(providers$Stamen.Watercolor) %>% addProviderTiles(providers$Stamen.TerrainLabels) %>% addCircleMarkers(~lon, ~lat, clusterOptions = markerClusterOptions()) ``` * **Your Turn** What else can you change about addCircleMarkers? Hint: Type `??addControl` Try adding: `clusterOptions = markerClusterOptions()` to your map. ] .right-plot[
] --- * Add labels ```r labels <- sprintf( "<strong>%s</strong>", work$institute) %>% lapply(htmltools::HTML) ``` --- .left-code[ ```r leaflet(work) %>% addProviderTiles(providers$Stamen.Watercolor) %>% addProviderTiles(providers$Stamen.TerrainLabels) %>% addCircleMarkers(~lon, ~lat, popup = ~labels) ``` ] .right-plot[
] --- layout: true # Useful resources: --- * [RStudio leaflet (Tutorial)](https://rstudio.github.io/leaflet/) * [Geocomputation with R (Book)](https://geocompr.robinlovelace.net/preface.html) * [Afrimapr: Intro to Spatial Data in R (Tutorial)](https://andysouth.shinyapps.io/intro-to-spatial-r/) * [Afrimapr: Getting Data into R (Tutorial) ](https://andysouth.shinyapps.io/get-my-data-in/) * [Afrimapr: Joining Spreadsheet Data (Tutorial) ](https://andysouth.shinyapps.io/get-my-data-in/) --- class: inverse, center, middle layout: true # Asante Sana! Slides created via the R package [xaringan](https://github.com/yihui/xaringan). The chakra comes from [remark.js](https://remarkjs.com), [knitr](http://yihui.org/knitr), and [R Markdown](https://rmarkdown.rstudio.com). .font150.text-white[ Special thanks to Rich Leyshon at the Data Science Campus and Kemunto Ongera at Bates College ] .font150.text-white[ Slides template adapted from Garrick Aden-Buie GitHub: <http://github.com/gadenbuie/gentle-ggplot2> ] ---