-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathr-spatial-data-and-mapping.html
More file actions
1342 lines (1312 loc) · 108 KB
/
Copy pathr-spatial-data-and-mapping.html
File metadata and controls
1342 lines (1312 loc) · 108 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
<meta charset="utf-8">
<meta name="generator" content="quarto-1.5.57">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<meta name="author" content="Maryna Shedzko">
<meta name="dcterms.date" content="2024-12-17">
<title>Spatial Data and Mapping in R</title>
<style>
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
div.columns{display: flex; gap: min(4vw, 1.5em);}
div.column{flex: auto; overflow-x: auto;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
ul.task-list{list-style: none;}
ul.task-list li input[type="checkbox"] {
width: 0.8em;
margin: 0 0.8em 0.2em -1em; /* quarto-specific, see https://github.com/quarto-dev/quarto-cli/issues/4556 */
vertical-align: middle;
}
/* CSS for syntax highlighting */
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { display: inline-block; text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
{ counter-reset: source-line 0; }
pre.numberSource code > span
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
{ content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
}
pre.numberSource { margin-left: 3em; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
</style>
<script src="r-spatial-data-and-mapping_files/libs/clipboard/clipboard.min.js"></script>
<script src="r-spatial-data-and-mapping_files/libs/quarto-html/quarto.js"></script>
<script src="r-spatial-data-and-mapping_files/libs/quarto-html/popper.min.js"></script>
<script src="r-spatial-data-and-mapping_files/libs/quarto-html/tippy.umd.min.js"></script>
<script src="r-spatial-data-and-mapping_files/libs/quarto-html/anchor.min.js"></script>
<link href="r-spatial-data-and-mapping_files/libs/quarto-html/tippy.css" rel="stylesheet">
<link href="r-spatial-data-and-mapping_files/libs/quarto-html/quarto-syntax-highlighting.css" rel="stylesheet" id="quarto-text-highlighting-styles">
<script src="r-spatial-data-and-mapping_files/libs/bootstrap/bootstrap.min.js"></script>
<link href="r-spatial-data-and-mapping_files/libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
<link href="r-spatial-data-and-mapping_files/libs/bootstrap/bootstrap.min.css" rel="stylesheet" id="quarto-bootstrap" data-mode="light">
</head>
<body>
<div id="quarto-content" class="page-columns page-rows-contents page-layout-article">
<div id="quarto-margin-sidebar" class="sidebar margin-sidebar">
<nav id="TOC" role="doc-toc" class="toc-active">
<h2 id="toc-title">Table of contents</h2>
<ul>
<li><a href="#talk-description" id="toc-talk-description" class="nav-link active" data-scroll-target="#talk-description"><strong>Talk Description</strong></a></li>
<li><a href="#introduction" id="toc-introduction" class="nav-link" data-scroll-target="#introduction"><strong>Introduction</strong></a></li>
<li><a href="#spatial-data" id="toc-spatial-data" class="nav-link" data-scroll-target="#spatial-data"><strong>Spatial Data</strong></a>
<ul class="collapse">
<li><a href="#vector-data" id="toc-vector-data" class="nav-link" data-scroll-target="#vector-data"><strong>Vector Data</strong></a>
<ul class="collapse">
<li><a href="#formats" id="toc-formats" class="nav-link" data-scroll-target="#formats">Formats</a></li>
<li><a href="#creating-spatial-objects" id="toc-creating-spatial-objects" class="nav-link" data-scroll-target="#creating-spatial-objects">Creating Spatial Objects</a></li>
<li><a href="#changing-geometry-types" id="toc-changing-geometry-types" class="nav-link" data-scroll-target="#changing-geometry-types">Changing Geometry Types</a></li>
</ul></li>
<li><a href="#basic-visualization" id="toc-basic-visualization" class="nav-link" data-scroll-target="#basic-visualization"><strong>Basic Visualization</strong></a></li>
<li><a href="#raster-data" id="toc-raster-data" class="nav-link" data-scroll-target="#raster-data"><strong>Raster data</strong></a>
<ul class="collapse">
<li><a href="#raster-spatial-information" id="toc-raster-spatial-information" class="nav-link" data-scroll-target="#raster-spatial-information">Raster spatial information</a></li>
<li><a href="#customizing-the-color-palette" id="toc-customizing-the-color-palette" class="nav-link" data-scroll-target="#customizing-the-color-palette">Customizing the Color Palette</a></li>
<li><a href="#cropping-the-raster" id="toc-cropping-the-raster" class="nav-link" data-scroll-target="#cropping-the-raster">Cropping the Raster</a></li>
<li><a href="#adding-raster-data-as-a-layer-to-a-map" id="toc-adding-raster-data-as-a-layer-to-a-map" class="nav-link" data-scroll-target="#adding-raster-data-as-a-layer-to-a-map"><strong>Adding Raster Data as a Layer to a Map</strong></a></li>
</ul></li>
</ul></li>
<li><a href="#how-to-make-pretty-maps-with-ggplot2" id="toc-how-to-make-pretty-maps-with-ggplot2" class="nav-link" data-scroll-target="#how-to-make-pretty-maps-with-ggplot2"><strong>How to make pretty maps with ggplot2</strong></a>
<ul class="collapse">
<li><a href="#creating-a-basic-map" id="toc-creating-a-basic-map" class="nav-link" data-scroll-target="#creating-a-basic-map">Creating a Basic Map</a></li>
<li><a href="#customizing-your-map" id="toc-customizing-your-map" class="nav-link" data-scroll-target="#customizing-your-map">Customizing your map</a>
<ul class="collapse">
<li><a href="#example-world-map-by-population" id="toc-example-world-map-by-population" class="nav-link" data-scroll-target="#example-world-map-by-population">Example: World Map by Population</a></li>
<li><a href="#example-elevation-map" id="toc-example-elevation-map" class="nav-link" data-scroll-target="#example-elevation-map">Example: Elevation Map</a></li>
<li><a href="#example-annual-precipitation-map" id="toc-example-annual-precipitation-map" class="nav-link" data-scroll-target="#example-annual-precipitation-map">Example: Annual Precipitation Map</a></li>
<li><a href="#going-beyond" id="toc-going-beyond" class="nav-link" data-scroll-target="#going-beyond"><strong>Going Beyond</strong></a></li>
</ul></li>
<li><a href="#how-to-make-pretty-maps-with-tmap" id="toc-how-to-make-pretty-maps-with-tmap" class="nav-link" data-scroll-target="#how-to-make-pretty-maps-with-tmap"><strong>How to make pretty maps with tmap</strong></a></li>
</ul></li>
</ul>
</nav>
</div>
<main class="content" id="quarto-document-content">
<header id="title-block-header" class="quarto-title-block default">
<div class="quarto-title">
<h1 class="title">Spatial Data and Mapping in R</h1>
</div>
<div class="quarto-title-meta-author">
<div class="quarto-title-meta-heading">Author</div>
<div class="quarto-title-meta-heading">Affiliation</div>
<div class="quarto-title-meta-contents">
<p class="author">Maryna Shedzko </p>
</div>
<div class="quarto-title-meta-contents">
<p class="affiliation">
ResearchIT, University of Manchester
</p>
</div>
</div>
<div class="quarto-title-meta">
<div>
<div class="quarto-title-meta-heading">Published</div>
<div class="quarto-title-meta-contents">
<p class="date">December 17, 2024</p>
</div>
</div>
</div>
</header>
<div class="cell">
<div class="sourceCode cell-code" id="cb1"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(sf)</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(dplyr)</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(rnaturalearth)</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(stars)</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(geodata)</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(ggplot2)</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(ggspatial)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<section id="talk-description" class="level1">
<h1><strong>Talk Description</strong></h1>
<p>Do you have an urge to know where? Discover how to bring your data to life through mapping! This talk introduces the basics of spatial data and how to create stunning maps in R. Using the beloved ggplot2, tmap, and the powerful sf package, we’ll explore visualizing vector and raster data, creating thematic maps, and customizing them. Whether you’re new to spatial data or looking to enhance your data visualization skills, this session will guide you through the essentials of mapping in R.</p>
<p>Speaker: Maryna Shedzko</p>
<p>Maryna is a Research Software Engineer with a background in GIS and Biogeography. During her studies, she specialized in disease distribution, particularly using R for modelling and spatial analysis.</p>
</section>
<section id="introduction" class="level1">
<h1><strong>Introduction</strong></h1>
<p>Welcome to Spatial Data and Mapping in R! In this talk, we will focus on building maps using <code>ggplot2</code>, one of R’s most popular libraries for data visualization. If you’re already familiar with creating graphs using <code>ggplot</code>, you’ll find making maps a natural extension of those skills.</p>
<p>We will also introduce <code>sf</code> (simple features), a package designed to work with spatial data in R. The combination of <code>ggplot2</code> and <code>sf</code> makes it possible to create beautiful, customizable maps with relatively little effort.</p>
</section>
<section id="spatial-data" class="level1">
<h1><strong>Spatial Data</strong></h1>
<p>Before we talk about mapping, we have to talk about spatial data.</p>
<p>Spatial data refers to information about spatial objects and their relationships. A spatial object is defined as a digital representation of a real or abstract object from the physical or virtual world, including its identifier, coordinates, and attribute data.</p>
<p>Simply put, spatial data consists of information about geographical features or phenomena, capturing their location and/or distribution within a coordinate system tied to the Earth or any other celestial body. What sets spatial data apart from non-spatial data is the use of coordinates to describe location.</p>
<p><strong>The vector model</strong> describes spatial objects using coordinates and, optionally, the topological relationships between them. Vector data captures the location and shape of objects as geometric primitives such as points, lines, polygons, and volumes. The choice of how to model an object (e.g., whether to represent a city as a point or a polygon) depends on the analysis scale and research objectives. The vector model is object-oriented.</p>
<p><strong>The raster model</strong>, on the other hand, doesn’t focus on objects but rather on the spatial distribution of a particular characteristic, chosen by the researcher.It divides space into a uniform grid of cells, each storing a value for the studied parameter (determined through averaging, center-point sampling, etc.). Raster data can be numerical, such as temperature measurements, or categorical, like a classified image where each cell corresponds to a specific category. Thus, the raster model is more focused on the space or phenomenon itself.</p>
<p>While there are other models of spatial data, we won’t be covering them today.</p>
<p>Today, we will focus on how to read and visualize spatial data in both vector and raster formats, and we’ll also discuss issues related to the use of cartographic projections.</p>
<section id="vector-data" class="level2">
<h2 class="anchored" data-anchor-id="vector-data"><strong>Vector Data</strong></h2>
<p>Simple Features (officially known as Simple Features Access) is a standard defined by the Open Geospatial Consortium (OGC) in document OGC 06-103, which is also recognized as the international standard ISO 19125. This standard outlines a common model for storing and accessing vector objects (such as points, lines, polygons, multi-points, multi-lines, etc.) in Geographic Information Systems (GIS).</p>
<p>The Simple Features standard includes 17 types of geometries in total. The most commonly used ones are the following seven:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="images/simple_features.png" class="img-fluid figure-img"></p>
<figcaption>Sketches of the main simple feature geometry types</figcaption>
</figure>
</div>
<p>For geographic coordinates (latitude and longitude), X corresponds to longitude, and Y corresponds to latitude.</p>
<section id="formats" class="level3">
<h3 class="anchored" data-anchor-id="formats">Formats</h3>
<p>Traditionally, in all GIS applications and spatial data databases, a large number of spatial objects are represented as an attribute table, where each row corresponds to an object and each column represents an attribute of that object. Each row in the table should be associated with information about the geometry of the object. Depending on the data format, this information can either be stored directly in the table (in a special column) or be placed in a separate data structure, which is linked to the attribute table via a key.</p>
<p>In R, the first approach is used by the <code>sf</code> package, where geometry information is stored in a special column of the table. Each cell in this column represents a Simple Features geometry object. The geometric objects are represented using standard structures such as lists, matrices, and vectors. These data structures store the coordinates of the objects in an ordered manner and naturally align with the data organization defined by the Simple Features standard. Since the geometry column doesn’t store regular variables but rather data structures, it is implemented as a list-column, with each element corresponding to a separate object.</p>
<p>to read the data we need to use the function <code>st_read</code></p>
<div class="cell">
<div class="sourceCode cell-code" id="cb2"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Read a geopackage</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>gpkg_path <span class="ot"><-</span> <span class="fu">file.path</span>(<span class="fu">getwd</span>(), <span class="st">"data"</span>, <span class="st">"countries"</span>, <span class="st">"countries_geopackage.gpkg"</span>)</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>gpkg_data <span class="ot"><-</span> <span class="fu">st_read</span>(gpkg_path)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>Reading layer `countries_shapefile' from data source
`C:\RIT\RMaps\r-spatial-data-and-mapping\data\countries\countries_geopackage.gpkg'
using driver `GPKG'
Simple feature collection with 242 features and 168 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: -180 ymin: -89.99893 xmax: 180 ymax: 83.59961
Geodetic CRS: WGS 84</code></pre>
</div>
</div>
<p>Spatial objects in R are represented through a hierarchy of three object classes:</p>
<ul>
<li><code>sf</code> (simple features): A data.frame object representing a collection of spatial objects with a list-column to store geometry.</li>
<li><code>sfc</code> (simple features geometry column): The list-column in an sf object that represents a collection of geometries for spatial objects.</li>
<li><code>sfg</code> (simple feature geometry): The geometry of a spatial object within the sfc list. With these specifications in mind, spatial objects are handled accordingly.</li>
</ul>
<p>The fact that Simple Features objects are implemented as regular data frames means that any operation applicable to a data frame can also be applied to sf objects. This is a crucial feature of sf objects, which was greatly missed in the ecosystem of the older <code>sp</code> package.</p>
<p>Lets have a look at the first five rows of the last 5 columns of the table</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb4"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="fu">head</span>(gpkg_data[<span class="fu">tail</span>(<span class="fu">colnames</span>(gpkg_data))])</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>Simple feature collection with 6 features and 5 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: -73.36621 ymin: -22.40205 xmax: 109.4449 ymax: 41.9062
Geodetic CRS: WGS 84
fclass_it fclass_nl fclass_se fclass_bd fclass_ua
1 <NA> <NA> <NA> <NA> <NA>
2 <NA> <NA> <NA> <NA> <NA>
3 <NA> <NA> <NA> <NA> <NA>
4 <NA> <NA> <NA> <NA> <NA>
5 <NA> <NA> <NA> <NA> <NA>
6 <NA> <NA> <NA> <NA> <NA>
geom
1 MULTIPOLYGON (((31.28789 -2...
2 MULTIPOLYGON (((30.39609 -1...
3 MULTIPOLYGON (((53.08564 16...
4 MULTIPOLYGON (((104.064 10....
5 MULTIPOLYGON (((-60.82119 9...
6 MULTIPOLYGON (((12.43916 41...</code></pre>
</div>
</div>
<p>The geometry is stored in a special column called <code>geometry</code> within the <code>sf</code> object. We can extract the geometry from this column using the <code>st_geometry()</code> function.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb6"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Extract geometry column</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>geom_data <span class="ot"><-</span> <span class="fu">st_geometry</span>(gpkg_data)</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="co"># Print the class of the extracted object</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="fu">class</span>(geom_data)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] "sfc_MULTIPOLYGON" "sfc" </code></pre>
</div>
</div>
<p>The extracted object will have the class <code>sfc</code> (Simple Features Geometry Column). This means it is a list of geometries, separate from the attribute data but still linked to the original spatial features.</p>
<p>Using <code>st_geometry()</code>, we can manipulate geometries separately from attribute data, allowing for operations such as transformations, projections, and spatial intersections while keeping attributes intact.</p>
<div style="color: #787474;">
<blockquote class="blockquote">
<p><strong>Note:</strong> It is worth mentioning that the <code>terra</code> package also has support for vector data through its <code>SpatVector</code> objects. Unlike <code>sf</code>, which stores geometry information within a special column in the attribute table, <code>terra</code> places geometry information in a separate data structure. This makes it a strong alternative for certain use cases, particularly because <code>terra</code> also handles raster datasets. However, we are focusing on <code>sf</code> in this talk because it offers a more data-frame-like approach. This can be more intuitive for GIS users, as it resembles traditional attribute tables, and for non-GIS users already familiar with <code>data.frame</code> structures in R. Additionally, <code>sf</code> integrates seamlessly with the `tidyverse ecosystem, making it easier for those who use <code>dplyr</code>, <code>ggplot2</code>, and other <code>tidyverse</code> tools</p>
</blockquote>
</div>
</section>
<section id="creating-spatial-objects" class="level3">
<h3 class="anchored" data-anchor-id="creating-spatial-objects">Creating Spatial Objects</h3>
<p>You can create your own spatial objects using the sf package. Depending on the type of geometry you want to create, the function you use will accept different input formats:</p>
<ul>
<li>Points: Use a coordinate vector.</li>
<li>Multipoints or Linestrings: Use a coordinate matrix.</li>
<li>Other Geometries (e.g., polygons): Use lists of coordinates.</li>
</ul>
<div class="cell">
<div class="sourceCode cell-code" id="cb8"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Create a Point (Single coordinate)</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>point <span class="ot"><-</span> <span class="fu">st_sfc</span>(<span class="fu">st_point</span>(<span class="fu">c</span>(<span class="dv">1</span>, <span class="dv">2</span>)))</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<div class="cell">
<div class="sourceCode cell-code" id="cb9"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Create a LineString (Matrix of coordinates)</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>ln <span class="ot"><-</span> <span class="fu">st_sfc</span>(<span class="fu">st_linestring</span>(<span class="fu">matrix</span>(<span class="fu">c</span>(<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>), <span class="at">ncol =</span> <span class="dv">2</span>)))</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<div class="cell">
<div class="sourceCode cell-code" id="cb10"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>coords <span class="ot"><-</span> <span class="fu">matrix</span>(<span class="fu">c</span>( </span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a> <span class="dv">0</span>, <span class="dv">0</span>,</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a> <span class="dv">1</span>, <span class="dv">0</span>,</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a> <span class="dv">1</span>, <span class="dv">1</span>,</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a> <span class="dv">0</span>, <span class="dv">1</span>,</span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a> <span class="dv">0</span>, <span class="dv">0</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>), <span class="at">ncol =</span> <span class="dv">2</span>, <span class="at">byrow =</span> <span class="cn">TRUE</span>)</span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a>pol <span class="ot"><-</span> <span class="fu">st_polygon</span>(<span class="fu">list</span>(coords)) <span class="co"># Simple polygon</span></span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a><span class="fu">plot</span>(pol)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="r-spatial-data-and-mapping_files/figure-html/unnamed-chunk-7-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
<div class="cell">
<div class="sourceCode cell-code" id="cb11"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>pol</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output cell-output-stderr">
<pre><code>POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))</code></pre>
</div>
</div>
</section>
<section id="changing-geometry-types" class="level3">
<h3 class="anchored" data-anchor-id="changing-geometry-types">Changing Geometry Types</h3>
<p>The <code>sf</code> package allows you to convert between different types of geometries using the <code>st_cast</code> function. For example, you might want to convert a polygon into a line, or vice versa. Here’s how you would do it:</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb13"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Convert a polygon into a Line</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>line_converted <span class="ot"><-</span> <span class="fu">st_cast</span>(pol, <span class="st">"LINESTRING"</span>)</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a><span class="fu">print</span>(line_converted)</span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a><span class="fu">plot</span>(line_converted)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="r-spatial-data-and-mapping_files/figure-html/unnamed-chunk-9-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
<p>Doesn’t look any different at first glance, but if we examine, we will notice that this object is now a linestring</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb14"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>line_converted</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output cell-output-stderr">
<pre><code>LINESTRING (0 0, 1 0, 1 1, 0 1, 0 0)</code></pre>
</div>
</div>
</section>
</section>
<section id="basic-visualization" class="level2">
<h2 class="anchored" data-anchor-id="basic-visualization"><strong>Basic Visualization</strong></h2>
<p>When using the <code>plot()</code> function on a spatial object (like an <code>sf</code> object), it will generate thematic maps for the first 9 attributes by default.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb16"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Get Natural Earth countries data</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>countries <span class="ot"><-</span> <span class="fu">ne_countries</span>(<span class="at">scale =</span> <span class="st">"medium"</span>, <span class="at">returnclass =</span> <span class="st">"sf"</span>)</span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a><span class="fu">plot</span>(countries)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="r-spatial-data-and-mapping_files/figure-html/unnamed-chunk-11-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
<p>To focus on a specific attribute, you can select it explicitly, as shown below:</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb17"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Get Natural Earth countries data</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a><span class="fu">plot</span>(countries[<span class="st">'name'</span>], <span class="at">key.pos =</span> <span class="cn">NULL</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="r-spatial-data-and-mapping_files/figure-html/unnamed-chunk-12-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
<p>If you want to visualize a specific country, like the Australia, you can filter the data and plot it separately:</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb18"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a>aus_sf <span class="ot"><-</span> countries <span class="sc">|></span> <span class="fu">filter</span>(name <span class="sc">==</span> <span class="st">"Australia"</span>)</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="fu">plot</span>(aus_sf)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="r-spatial-data-and-mapping_files/figure-html/unnamed-chunk-13-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
<div style="color: #787474;">
<blockquote class="blockquote">
<p><strong>Note:</strong> In the example above, the base R pipe operator (<code>|></code>) is used to pass the data from one function to the next. It simplifies the workflow by eliminating the need for nested function calls. The expression <code>countries |> filter(name == "Australia")</code> filters the dataset for the Australia, and the filtered result is immediately passed to the <code>plot()</code> function for visualization.</p>
</blockquote>
</div>
<p>For a more focused plot, select a particular attribute of the UK:</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb19"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a>aus_sf <span class="ot"><-</span> countries <span class="sc">|></span> <span class="fu">filter</span>(name <span class="sc">==</span> <span class="st">"Australia"</span>)</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a><span class="fu">plot</span>(aus_sf[<span class="st">"sovereignt"</span>])</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="r-spatial-data-and-mapping_files/figure-html/unnamed-chunk-14-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
<p>You can also filter countries by population. For example, to plot countries with a population greater than 50 million:</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb20"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Plotting Countries with Population Greater Than 50 Million</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>outlines <span class="ot"><-</span> <span class="fu">st_geometry</span>(countries)</span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>high_pop_sf <span class="ot"><-</span> countries <span class="sc">|></span> <span class="fu">filter</span>(pop_est <span class="sc">></span> <span class="dv">50000000</span>)</span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a><span class="fu">plot</span>(outlines, <span class="at">col =</span> <span class="st">'lightgrey'</span>)</span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a><span class="fu">plot</span>(high_pop_sf<span class="sc">$</span>geometry, <span class="at">col =</span> <span class="st">'blue'</span>, <span class="at">add =</span> <span class="cn">TRUE</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="r-spatial-data-and-mapping_files/figure-html/unnamed-chunk-15-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
<p>You can add extra features to your plot, such as a graticule (grid lines) and axes:</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb21"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="fu">plot</span>(countries[<span class="st">"pop_est"</span>], <span class="at">graticule =</span> <span class="cn">TRUE</span>, <span class="at">axes =</span> <span class="cn">TRUE</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="r-spatial-data-and-mapping_files/figure-html/unnamed-chunk-16-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
<p>You can combine different layers to enhance your visualization. For example, here’s how to add oceans and populated places to the Australia map:</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb22"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Download more Natural Earth data</span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>oceans <span class="ot"><-</span> <span class="fu">ne_download</span>(<span class="at">scale =</span> <span class="st">"medium"</span>, <span class="at">type =</span> <span class="st">"ocean"</span>, <span class="at">category =</span> <span class="st">"physical"</span>, <span class="at">returnclass =</span> <span class="st">"sf"</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>Reading layer `ne_50m_ocean' from data source
`C:\Users\n46797ms\AppData\Local\Temp\RtmpaABuKG\ne_50m_ocean.shp'
using driver `ESRI Shapefile'
Simple feature collection with 1 feature and 3 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: -180 ymin: -85.19219 xmax: 180 ymax: 90
Geodetic CRS: WGS 84</code></pre>
</div>
<div class="sourceCode cell-code" id="cb24"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a>cities <span class="ot"><-</span> <span class="fu">ne_download</span>(<span class="at">scale =</span> <span class="st">"medium"</span>, <span class="at">type =</span> <span class="st">"populated_places_simple"</span>, <span class="at">returnclass =</span> <span class="st">"sf"</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>Reading layer `ne_50m_populated_places_simple' from data source
`C:\Users\n46797ms\AppData\Local\Temp\RtmpaABuKG\ne_50m_populated_places_simple.shp'
using driver `ESRI Shapefile'
Simple feature collection with 1251 features and 31 fields
Geometry type: POINT
Dimension: XY
Bounding box: xmin: -175.2206 ymin: -90 xmax: 179.2166 ymax: 78.22097
Geodetic CRS: WGS 84</code></pre>
</div>
<div class="sourceCode cell-code" id="cb26"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Filter for UK cities and select the top 10 by population</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a>aus_cities <span class="ot"><-</span> cities <span class="sc">|></span></span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">filter</span>(sov0name <span class="sc">==</span> <span class="st">"Australia"</span>) <span class="sc">|></span></span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">arrange</span>(<span class="fu">desc</span>(pop_max)) <span class="sc">|></span></span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a> <span class="fu">slice_head</span>(<span class="at">n =</span> <span class="dv">5</span>)</span>
<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-7"><a href="#cb26-7" aria-hidden="true" tabindex="-1"></a><span class="co"># Plot the map</span></span>
<span id="cb26-8"><a href="#cb26-8" aria-hidden="true" tabindex="-1"></a><span class="fu">plot</span>(<span class="fu">st_geometry</span>(aus_sf), <span class="at">lwd =</span> <span class="fl">0.5</span>, <span class="at">border =</span> <span class="st">'gray'</span>, <span class="at">main =</span> <span class="st">"Australia with Top 5 Largest Cities"</span>)</span>
<span id="cb26-9"><a href="#cb26-9" aria-hidden="true" tabindex="-1"></a><span class="fu">plot</span>(<span class="fu">st_geometry</span>(oceans), <span class="at">col =</span> <span class="st">'steelblue1'</span>, <span class="at">border =</span> <span class="st">'steelblue'</span>, <span class="at">add =</span> <span class="cn">TRUE</span>)</span>
<span id="cb26-10"><a href="#cb26-10" aria-hidden="true" tabindex="-1"></a><span class="fu">plot</span>(<span class="fu">st_geometry</span>(aus_sf), <span class="at">border =</span> <span class="st">"black"</span>, <span class="at">lwd =</span> <span class="dv">1</span>, <span class="at">col =</span> <span class="cn">NA</span>, <span class="at">add =</span> <span class="cn">TRUE</span>)</span>
<span id="cb26-11"><a href="#cb26-11" aria-hidden="true" tabindex="-1"></a><span class="fu">plot</span>(<span class="fu">st_geometry</span>(aus_cities), <span class="at">col =</span> <span class="st">'black'</span>, <span class="at">pch =</span> <span class="dv">19</span>, <span class="at">cex =</span> <span class="dv">1</span>, <span class="at">add =</span> <span class="cn">TRUE</span>)</span>
<span id="cb26-12"><a href="#cb26-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-13"><a href="#cb26-13" aria-hidden="true" tabindex="-1"></a><span class="co"># Add city labels</span></span>
<span id="cb26-14"><a href="#cb26-14" aria-hidden="true" tabindex="-1"></a><span class="fu">text</span>(aus_cities<span class="sc">$</span>longitude, aus_cities<span class="sc">$</span>latitude,</span>
<span id="cb26-15"><a href="#cb26-15" aria-hidden="true" tabindex="-1"></a> <span class="at">labels =</span> aus_cities<span class="sc">$</span>name, <span class="at">cex =</span> <span class="fl">0.8</span>, <span class="at">pos =</span> <span class="dv">2</span>, <span class="at">offset =</span> <span class="fl">0.25</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="r-spatial-data-and-mapping_files/figure-html/unnamed-chunk-17-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="raster-data" class="level2">
<h2 class="anchored" data-anchor-id="raster-data"><strong>Raster data</strong></h2>
<p>A raster is a type of spatial data that represents information in a grid format, consisting of cells (or pixels), each with a value that represents some measurement or attribute for that location. This grid-based format is commonly used for representing continuous data such as elevation, temperature, land cover, or satellite imagery.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="images/raster_concept.png" class="img-fluid figure-img"></p>
<figcaption>Raster. Source: National Ecological Observatory Network (NEON)</figcaption>
</figure>
</div>
<p>Unlike vector data, which requires specifying coordinates for each vertex, the regular grid structure of raster data allows the coordinates of the pixels to be calculated based on their indices. Therefore, raster data is essentially stored as a linearly ordered list of raster values and a description of the raster’s spatial information.</p>
<section id="raster-spatial-information" class="level3">
<h3 class="anchored" data-anchor-id="raster-spatial-information">Raster spatial information</h3>
<p>The spatial information of a raster refers to the location of its pixels and can be described by the following components:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Parameter</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>NCOLS</td>
<td>Number of columns</td>
</tr>
<tr class="even">
<td>NROWS</td>
<td>Number of rows</td>
</tr>
<tr class="odd">
<td>XLLCENTER</td>
<td>Coordinates of the center of the lower-left pixel</td>
</tr>
<tr class="even">
<td>YLLCENTER</td>
<td>Coordinates of the center of the lower-left pixel</td>
</tr>
<tr class="odd">
<td>CELLSIZE</td>
<td>Size of each pixel</td>
</tr>
</tbody>
</table>
<p>There are two packages that are widely used to work with raster data: <code>stars</code> and <code>terra</code>. Terra evolved from <code>raster</code> package, which used to be a primary tool for working with raster data. <code>stars</code> on the other hand, was developed to support multidimensional data and provide close integration with <code>sf</code>.</p>
<div style="color: #787474;">
<blockquote class="blockquote">
<p><strong>Note:</strong> In this talk, we will be using the <code>stars</code> package because it is compatible with <code>sf</code>, making it easier to work seamlessly with both vector and raster data. However, <code>terra</code> is a powerful alternative for raster data analysis and is particularly well-suited for large datasets and advanced geospatial operations.</p>
</blockquote>
</div>
<p>Another package worth mentioning is <code>geodata</code>, which used to be part of the raster package but became its own independent package. This package allows you to easily access various global environmental data, such as climate, elevation, and land cover datasets, and import them directly into R. It provides convenient functions for fetching these datasets without the need to manually download and preprocess them.</p>
<p>Let’s start by importing some raster data and visualizing it. For this example, we’ll use elevation data.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb27"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(stars)</span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a>elevation_st <span class="ot"><-</span> <span class="fu">read_stars</span>(<span class="st">"data/elevation/gebco_small.tif"</span>)</span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a><span class="fu">plot</span>(elevation_st)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="r-spatial-data-and-mapping_files/figure-html/unnamed-chunk-18-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
<p>This basic plot gives us a look at the elevation data. But we can customize how the data looks by changing color schemes, breaking the values into bins, or cutting out specific areas.</p>
</section>
<section id="customizing-the-color-palette" class="level3">
<h3 class="anchored" data-anchor-id="customizing-the-color-palette">Customizing the Color Palette</h3>
<p>You can create custom color palettes by defining breakpoints and selecting colors. Here’s how we can create a palette for elevation data:</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb28"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a>brks <span class="ot"><-</span> <span class="fu">c</span>(<span class="sc">-</span><span class="dv">12000</span>, <span class="sc">-</span><span class="dv">5000</span>, <span class="sc">-</span><span class="dv">2500</span>, <span class="sc">-</span><span class="dv">1000</span>, <span class="sc">-</span><span class="dv">200</span>, <span class="dv">0</span>, <span class="dv">200</span>, <span class="dv">500</span>, <span class="dv">1000</span>, <span class="dv">2000</span>, <span class="dv">4000</span>, <span class="dv">8000</span>)</span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a>clrs <span class="ot"><-</span> <span class="fu">c</span>(</span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a> <span class="st">"steelblue4"</span>,</span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a> <span class="st">"steelblue3"</span>,</span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a> <span class="st">"steelblue2"</span>,</span>
<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a> <span class="st">"steelblue1"</span>,</span>
<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a> <span class="st">"lightskyblue1"</span>,</span>
<span id="cb28-8"><a href="#cb28-8" aria-hidden="true" tabindex="-1"></a> <span class="st">"darkseagreen"</span>,</span>
<span id="cb28-9"><a href="#cb28-9" aria-hidden="true" tabindex="-1"></a> <span class="st">"lightgoldenrod1"</span>,</span>
<span id="cb28-10"><a href="#cb28-10" aria-hidden="true" tabindex="-1"></a> <span class="st">"darkgoldenrod1"</span>,</span>
<span id="cb28-11"><a href="#cb28-11" aria-hidden="true" tabindex="-1"></a> <span class="st">"darkorange"</span>,</span>
<span id="cb28-12"><a href="#cb28-12" aria-hidden="true" tabindex="-1"></a> <span class="st">"coral2"</span>,</span>
<span id="cb28-13"><a href="#cb28-13" aria-hidden="true" tabindex="-1"></a> <span class="st">"firebrick3"</span>)</span>
<span id="cb28-14"><a href="#cb28-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-15"><a href="#cb28-15" aria-hidden="true" tabindex="-1"></a><span class="fu">plot</span>(elevation_st, <span class="at">breaks =</span> brks, <span class="at">col =</span> clrs)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="r-spatial-data-and-mapping_files/figure-html/unnamed-chunk-19-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
<p>Alternatively, you can use existing color palettes, like rainbow (there are many to choose from!)</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb29"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="fu">plot</span>(elevation_st, <span class="at">col =</span> <span class="fu">rainbow</span>(<span class="dv">10</span>))</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="r-spatial-data-and-mapping_files/figure-html/unnamed-chunk-20-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="cropping-the-raster" class="level3">
<h3 class="anchored" data-anchor-id="cropping-the-raster">Cropping the Raster</h3>
<p>Sometimes, you may want to focus on a specific area within your raster data. You can crop the raster using a polygon, such as focusing on a specific country. In this case, we’ll focus on Australia, and we’ll use the <code>terrain.colors</code> palette to visualize the elevation data.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb30"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Filter for Australia from the countries dataset</span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a>australia <span class="ot"><-</span> countries <span class="sc">|></span> <span class="fu">filter</span>(name <span class="sc">==</span> <span class="st">"Australia"</span>) <span class="sc">|></span> <span class="fu">st_as_sf</span>()</span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a><span class="co"># Crop the elevation data for Australia</span></span>
<span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a>elev_country <span class="ot"><-</span> elevation_st[australia]</span>
<span id="cb30-6"><a href="#cb30-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-7"><a href="#cb30-7" aria-hidden="true" tabindex="-1"></a><span class="co"># Plot the cropped elevation data with the terrain.colors palette</span></span>
<span id="cb30-8"><a href="#cb30-8" aria-hidden="true" tabindex="-1"></a><span class="fu">plot</span>(elev_country, <span class="at">col =</span> <span class="fu">terrain.colors</span>(<span class="dv">6</span>))</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="r-spatial-data-and-mapping_files/figure-html/unnamed-chunk-21-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="adding-raster-data-as-a-layer-to-a-map" class="level3">
<h3 class="anchored" data-anchor-id="adding-raster-data-as-a-layer-to-a-map"><strong>Adding Raster Data as a Layer to a Map</strong></h3>
<p>You can also overlay raster data onto vector data in a map. Let’s use the map of Australia with top cities, and add the cropped elevation data as a layer.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb31"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Filter for Australia and top 5 cities by population</span></span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a>aus_cities <span class="ot"><-</span> cities <span class="sc">|></span></span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">filter</span>(sov0name <span class="sc">==</span> <span class="st">"Australia"</span>) <span class="sc">|></span></span>
<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">arrange</span>(<span class="fu">desc</span>(pop_max)) <span class="sc">|></span></span>
<span id="cb31-5"><a href="#cb31-5" aria-hidden="true" tabindex="-1"></a> <span class="fu">slice_head</span>(<span class="at">n =</span> <span class="dv">5</span>)</span>
<span id="cb31-6"><a href="#cb31-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-7"><a href="#cb31-7" aria-hidden="true" tabindex="-1"></a><span class="co"># Plot the map</span></span>
<span id="cb31-8"><a href="#cb31-8" aria-hidden="true" tabindex="-1"></a><span class="fu">plot</span>(australia<span class="sc">$</span>geometry, <span class="at">lwd =</span> <span class="fl">0.5</span>, <span class="at">border =</span> <span class="st">'gray'</span>, <span class="at">main =</span> <span class="st">"Australia with Top 5 Largest Cities"</span>) <span class="co"># Custom title</span></span>
<span id="cb31-9"><a href="#cb31-9" aria-hidden="true" tabindex="-1"></a><span class="fu">plot</span>(oceans, <span class="at">col =</span> <span class="st">'steelblue1'</span>, <span class="at">border =</span> <span class="st">'steelblue'</span>, <span class="at">add =</span> <span class="cn">TRUE</span>)</span>
<span id="cb31-10"><a href="#cb31-10" aria-hidden="true" tabindex="-1"></a><span class="fu">plot</span>(australia<span class="sc">$</span>geometry, <span class="at">border =</span> <span class="st">"black"</span>, <span class="at">lwd =</span> <span class="dv">1</span>, <span class="at">col =</span> <span class="cn">NA</span>, <span class="at">add =</span> <span class="cn">TRUE</span>)</span>
<span id="cb31-11"><a href="#cb31-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-12"><a href="#cb31-12" aria-hidden="true" tabindex="-1"></a><span class="co"># Add the elevation raster data</span></span>
<span id="cb31-13"><a href="#cb31-13" aria-hidden="true" tabindex="-1"></a><span class="fu">plot</span>(elev_country, <span class="at">col =</span> <span class="fu">terrain.colors</span>(<span class="dv">6</span>), <span class="at">add =</span> <span class="cn">TRUE</span>, <span class="at">main =</span> <span class="cn">NULL</span>)</span>
<span id="cb31-14"><a href="#cb31-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-15"><a href="#cb31-15" aria-hidden="true" tabindex="-1"></a><span class="co"># Plot cities</span></span>
<span id="cb31-16"><a href="#cb31-16" aria-hidden="true" tabindex="-1"></a><span class="fu">plot</span>(aus_cities, <span class="at">col =</span> <span class="st">'black'</span>, <span class="at">pch =</span> <span class="dv">19</span>, <span class="at">cex =</span> <span class="dv">1</span>, <span class="at">add =</span> <span class="cn">TRUE</span>)</span>
<span id="cb31-17"><a href="#cb31-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-18"><a href="#cb31-18" aria-hidden="true" tabindex="-1"></a><span class="co"># Add city labels</span></span>
<span id="cb31-19"><a href="#cb31-19" aria-hidden="true" tabindex="-1"></a><span class="fu">text</span>(aus_cities<span class="sc">$</span>longitude, aus_cities<span class="sc">$</span>latitude,</span>
<span id="cb31-20"><a href="#cb31-20" aria-hidden="true" tabindex="-1"></a> <span class="at">labels =</span> aus_cities<span class="sc">$</span>name, <span class="at">cex =</span> <span class="fl">0.8</span>, <span class="at">pos =</span> <span class="dv">2</span>, <span class="at">offset =</span> <span class="fl">0.25</span>)</span>
<span id="cb31-21"><a href="#cb31-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-22"><a href="#cb31-22" aria-hidden="true" tabindex="-1"></a><span class="co"># Add grid for visual aid</span></span>
<span id="cb31-23"><a href="#cb31-23" aria-hidden="true" tabindex="-1"></a><span class="fu">grid</span>()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="r-spatial-data-and-mapping_files/figure-html/unnamed-chunk-22-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
<p>This creates a map of Australia with top cities overlaid, and it includes the cropped elevation data as an additional layer. It does not look particularly pretty, but this is something you can do in base R!</p>
</section>
</section>
</section>
<section id="how-to-make-pretty-maps-with-ggplot2" class="level1">
<h1><strong>How to make pretty maps with ggplot2</strong></h1>
<p>In previous section we explored that capabilities of base R t visualize raster and vector data. In this section we are going to look at ggplot2, as it offers a more flexible and aesthetically pleasing approach.</p>
<section id="creating-a-basic-map" class="level2">
<h2 class="anchored" data-anchor-id="creating-a-basic-map">Creating a Basic Map</h2>
<p>While <code>ggplot2</code> syntax can seem a bit more complicated compared to base R plots, it’s very similar to creating regular plots. Essentially, ggplot2 allows you to layer different elements onto your plot, making it highly flexible and powerful for both simple and complex visualizations.</p>
<p>When working with maps, we treat the spatial data as a special type of dataset. A key difference with regular graphs is that spatial data usually comes in the form of vector data (like points, lines, or polygons) or raster data (like grids of values). But we use the same ggplot2 syntax for both!</p>
<p>Just like when creating regular graphs, we need to specify the geom to determine how our data will be represented visually.</p>
<p>For example:</p>
<ul>
<li>In regular graphs, when plotting points, we use <code>geom_point()</code>.</li>
<li>For spatial data, the equivalent for vector data (like countries or polygons) is <code>geom_sf()</code>.</li>
<li>For raster data (like elevation or temperature grids), we use <code>geom_stars()</code>. Here’s an example comparing a scatter plot (a regular graph) and a map (spatial data) using ggplot2:</li>
</ul>
<div class="cell">
<div class="sourceCode cell-code" id="cb32"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Example of a simple scatter plot</span></span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a><span class="fu">ggplot</span>(<span class="at">data =</span> mtcars, <span class="fu">aes</span>(<span class="at">x =</span> wt, <span class="at">y =</span> mpg)) <span class="sc">+</span> <span class="co"># Dataset and aesthetic mapping</span></span>
<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">geom_point</span>() <span class="sc">+</span> <span class="co"># Plot the points</span></span>
<span id="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">labs</span>(</span>
<span id="cb32-5"><a href="#cb32-5" aria-hidden="true" tabindex="-1"></a> <span class="at">title =</span> <span class="st">"Car Weight vs. Miles Per Gallon"</span>, <span class="co"># Add a title</span></span>
<span id="cb32-6"><a href="#cb32-6" aria-hidden="true" tabindex="-1"></a> <span class="at">caption =</span> <span class="st">"Data Source: mtcars"</span> <span class="co"># Add a caption</span></span>
<span id="cb32-7"><a href="#cb32-7" aria-hidden="true" tabindex="-1"></a> ) <span class="sc">+</span></span>
<span id="cb32-8"><a href="#cb32-8" aria-hidden="true" tabindex="-1"></a> <span class="fu">theme_minimal</span>() <span class="co"># Use the same minimal theme</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="r-spatial-data-and-mapping_files/figure-html/unnamed-chunk-23-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
<div class="cell">
<div class="sourceCode cell-code" id="cb33"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Load Natural Earth countries dataset</span></span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a>countries <span class="ot"><-</span> <span class="fu">ne_countries</span>(<span class="at">scale =</span> <span class="st">"medium"</span>, <span class="at">returnclass =</span> <span class="st">"sf"</span>)</span>
<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a><span class="co"># Create a simple map using ggplot</span></span>
<span id="cb33-5"><a href="#cb33-5" aria-hidden="true" tabindex="-1"></a><span class="fu">ggplot</span>(<span class="at">data =</span> countries) <span class="sc">+</span></span>
<span id="cb33-6"><a href="#cb33-6" aria-hidden="true" tabindex="-1"></a> <span class="fu">geom_sf</span>() <span class="sc">+</span></span>
<span id="cb33-7"><a href="#cb33-7" aria-hidden="true" tabindex="-1"></a> <span class="fu">labs</span>(</span>
<span id="cb33-8"><a href="#cb33-8" aria-hidden="true" tabindex="-1"></a> <span class="at">title =</span> <span class="st">"World Map"</span>,</span>
<span id="cb33-9"><a href="#cb33-9" aria-hidden="true" tabindex="-1"></a> <span class="at">caption =</span> <span class="st">"Data Source: Natural Earth"</span></span>
<span id="cb33-10"><a href="#cb33-10" aria-hidden="true" tabindex="-1"></a> ) <span class="sc">+</span></span>
<span id="cb33-11"><a href="#cb33-11" aria-hidden="true" tabindex="-1"></a> <span class="fu">theme_minimal</span>()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="r-spatial-data-and-mapping_files/figure-html/unnamed-chunk-24-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
<p>So, if you’ve used ggplot2 before, it should be straightforward to apply the same principles to create maps!</p>
</section>
<section id="customizing-your-map" class="level2">
<h2 class="anchored" data-anchor-id="customizing-your-map">Customizing your map</h2>
<section id="example-world-map-by-population" class="level3">
<h3 class="anchored" data-anchor-id="example-world-map-by-population">Example: World Map by Population</h3>
<p>Just like regular graphs, you can also customize the map in many ways. For instance, in the next example, we’ll color the countries based on their population class.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb34"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a>countries<span class="sc">$</span>pop_class <span class="ot"><-</span> <span class="fu">cut</span>(countries<span class="sc">$</span>pop_est, </span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a> <span class="at">breaks =</span> <span class="fu">c</span>(<span class="dv">0</span>, <span class="fl">1e6</span>, <span class="fl">10e6</span>, <span class="fl">50e6</span>, <span class="fl">200e6</span>, <span class="fl">1e9</span>, <span class="cn">Inf</span>), </span>
<span id="cb34-3"><a href="#cb34-3" aria-hidden="true" tabindex="-1"></a> <span class="at">labels =</span> <span class="fu">c</span>(<span class="st">"<1M"</span>, <span class="st">"1-10M"</span>, <span class="st">"10-50M"</span>, <span class="st">"50-200M"</span>, <span class="st">"200M-1B"</span>, <span class="st">">1B"</span>),</span>
<span id="cb34-4"><a href="#cb34-4" aria-hidden="true" tabindex="-1"></a> <span class="at">include.lowest =</span> <span class="cn">TRUE</span>)</span>
<span id="cb34-5"><a href="#cb34-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb34-6"><a href="#cb34-6" aria-hidden="true" tabindex="-1"></a><span class="fu">ggplot</span>(<span class="at">data =</span> countries) <span class="sc">+</span></span>
<span id="cb34-7"><a href="#cb34-7" aria-hidden="true" tabindex="-1"></a> <span class="fu">geom_sf</span>(<span class="fu">aes</span>(<span class="at">fill =</span> pop_class), <span class="at">color =</span> <span class="cn">NA</span>) <span class="sc">+</span></span>
<span id="cb34-8"><a href="#cb34-8" aria-hidden="true" tabindex="-1"></a> <span class="fu">scale_fill_manual</span>(<span class="at">values =</span> <span class="fu">c</span>(</span>
<span id="cb34-9"><a href="#cb34-9" aria-hidden="true" tabindex="-1"></a> <span class="st">"<1M"</span> <span class="ot">=</span> <span class="st">"#ffffff"</span>, <span class="co"># White</span></span>
<span id="cb34-10"><a href="#cb34-10" aria-hidden="true" tabindex="-1"></a> <span class="st">"1-10M"</span> <span class="ot">=</span> <span class="st">"#fee5d9"</span>,</span>
<span id="cb34-11"><a href="#cb34-11" aria-hidden="true" tabindex="-1"></a> <span class="st">"10-50M"</span> <span class="ot">=</span> <span class="st">"#fcae91"</span>,</span>
<span id="cb34-12"><a href="#cb34-12" aria-hidden="true" tabindex="-1"></a> <span class="st">"50-200M"</span> <span class="ot">=</span> <span class="st">"#fb6a4a"</span>,</span>
<span id="cb34-13"><a href="#cb34-13" aria-hidden="true" tabindex="-1"></a> <span class="st">"200M-1B"</span> <span class="ot">=</span> <span class="st">"#de2d26"</span>,</span>
<span id="cb34-14"><a href="#cb34-14" aria-hidden="true" tabindex="-1"></a> <span class="st">">1B"</span> <span class="ot">=</span> <span class="st">"#a50f15"</span> <span class="co"># Dark Red</span></span>
<span id="cb34-15"><a href="#cb34-15" aria-hidden="true" tabindex="-1"></a> )) <span class="sc">+</span></span>
<span id="cb34-16"><a href="#cb34-16" aria-hidden="true" tabindex="-1"></a> <span class="fu">labs</span>(</span>
<span id="cb34-17"><a href="#cb34-17" aria-hidden="true" tabindex="-1"></a> <span class="at">title =</span> <span class="st">"World Map by Population"</span>,</span>
<span id="cb34-18"><a href="#cb34-18" aria-hidden="true" tabindex="-1"></a> <span class="at">fill =</span> <span class="st">"Population Class"</span>,</span>
<span id="cb34-19"><a href="#cb34-19" aria-hidden="true" tabindex="-1"></a> <span class="at">caption =</span> <span class="st">"Data Source: Natural Earth"</span></span>
<span id="cb34-20"><a href="#cb34-20" aria-hidden="true" tabindex="-1"></a> ) <span class="sc">+</span></span>
<span id="cb34-21"><a href="#cb34-21" aria-hidden="true" tabindex="-1"></a> <span class="fu">coord_sf</span>(<span class="at">expand =</span> <span class="cn">FALSE</span>) </span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="r-spatial-data-and-mapping_files/figure-html/unnamed-chunk-25-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
<ul>
<li><code>aes(fill = pop_class)</code> maps the population class to colors.</li>
<li><code>geom_sf()</code> is still used to plot the geometry (countries), but we added color based on population classes.</li>
<li><code>scale_fill_manual()</code> customizes the color palette for the population categories.</li>
</ul>
</section>
<section id="example-elevation-map" class="level3">
<h3 class="anchored" data-anchor-id="example-elevation-map">Example: Elevation Map</h3>
<p>Next, let’s visualize elevation data by creating a map using raster data. In this case, we’ll color the elevation based on binned categories.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb35"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Define the breaks and colors</span></span>
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a>brks <span class="ot"><-</span> <span class="fu">c</span>(<span class="sc">-</span><span class="dv">12000</span>, <span class="sc">-</span><span class="dv">5000</span>, <span class="sc">-</span><span class="dv">2500</span>, <span class="sc">-</span><span class="dv">1000</span>, <span class="sc">-</span><span class="dv">200</span>, <span class="dv">0</span>, <span class="dv">200</span>, <span class="dv">500</span>, <span class="dv">1000</span>, <span class="dv">2000</span>, <span class="dv">4000</span>, <span class="dv">8000</span>)</span>
<span id="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a>clrs <span class="ot"><-</span> <span class="fu">c</span>(</span>
<span id="cb35-4"><a href="#cb35-4" aria-hidden="true" tabindex="-1"></a> <span class="st">"steelblue4"</span>, <span class="st">"steelblue3"</span>, <span class="st">"steelblue2"</span>, <span class="st">"steelblue1"</span>, <span class="st">"lightskyblue1"</span>,</span>
<span id="cb35-5"><a href="#cb35-5" aria-hidden="true" tabindex="-1"></a> <span class="st">"darkseagreen"</span>, <span class="st">"lightgoldenrod1"</span>, <span class="st">"darkgoldenrod1"</span>, <span class="st">"darkorange"</span>,</span>
<span id="cb35-6"><a href="#cb35-6" aria-hidden="true" tabindex="-1"></a> <span class="st">"coral2"</span>, <span class="st">"firebrick3"</span></span>
<span id="cb35-7"><a href="#cb35-7" aria-hidden="true" tabindex="-1"></a>)</span>
<span id="cb35-8"><a href="#cb35-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-9"><a href="#cb35-9" aria-hidden="true" tabindex="-1"></a><span class="co"># Cut the elevation data into bins based on the breaks</span></span>
<span id="cb35-10"><a href="#cb35-10" aria-hidden="true" tabindex="-1"></a>elevation_st<span class="sc">$</span>elevation_binned <span class="ot"><-</span> <span class="fu">cut</span>(</span>
<span id="cb35-11"><a href="#cb35-11" aria-hidden="true" tabindex="-1"></a> elevation_st[[<span class="dv">1</span>]], </span>
<span id="cb35-12"><a href="#cb35-12" aria-hidden="true" tabindex="-1"></a> <span class="at">breaks =</span> brks, </span>
<span id="cb35-13"><a href="#cb35-13" aria-hidden="true" tabindex="-1"></a> <span class="at">include.lowest =</span> <span class="cn">TRUE</span></span>
<span id="cb35-14"><a href="#cb35-14" aria-hidden="true" tabindex="-1"></a>)</span>
<span id="cb35-15"><a href="#cb35-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-16"><a href="#cb35-16" aria-hidden="true" tabindex="-1"></a><span class="co"># Create the plot</span></span>
<span id="cb35-17"><a href="#cb35-17" aria-hidden="true" tabindex="-1"></a><span class="fu">ggplot</span>() <span class="sc">+</span></span>
<span id="cb35-18"><a href="#cb35-18" aria-hidden="true" tabindex="-1"></a> <span class="co"># Elevation raster data</span></span>
<span id="cb35-19"><a href="#cb35-19" aria-hidden="true" tabindex="-1"></a> <span class="fu">geom_stars</span>(<span class="at">data =</span> elevation_st, <span class="fu">aes</span>(<span class="at">fill =</span> elevation_binned)) <span class="sc">+</span></span>
<span id="cb35-20"><a href="#cb35-20" aria-hidden="true" tabindex="-1"></a> <span class="fu">scale_fill_manual</span>(</span>
<span id="cb35-21"><a href="#cb35-21" aria-hidden="true" tabindex="-1"></a> <span class="at">values =</span> clrs,</span>
<span id="cb35-22"><a href="#cb35-22" aria-hidden="true" tabindex="-1"></a> <span class="at">name =</span> <span class="st">"Elevation (m)"</span>,</span>
<span id="cb35-23"><a href="#cb35-23" aria-hidden="true" tabindex="-1"></a> <span class="at">labels =</span> <span class="fu">c</span>(</span>
<span id="cb35-24"><a href="#cb35-24" aria-hidden="true" tabindex="-1"></a> <span class="st">" < -5000"</span>, </span>
<span id="cb35-25"><a href="#cb35-25" aria-hidden="true" tabindex="-1"></a> <span class="st">"-5000 - -2500"</span>, </span>
<span id="cb35-26"><a href="#cb35-26" aria-hidden="true" tabindex="-1"></a> <span class="st">"-2500 - -1000"</span>, </span>
<span id="cb35-27"><a href="#cb35-27" aria-hidden="true" tabindex="-1"></a> <span class="st">"-1000-200"</span>, </span>
<span id="cb35-28"><a href="#cb35-28" aria-hidden="true" tabindex="-1"></a> <span class="st">"-200-0"</span>, </span>
<span id="cb35-29"><a href="#cb35-29" aria-hidden="true" tabindex="-1"></a> <span class="st">"0 - 200"</span>,</span>
<span id="cb35-30"><a href="#cb35-30" aria-hidden="true" tabindex="-1"></a> <span class="st">"200 - 500"</span>,</span>
<span id="cb35-31"><a href="#cb35-31" aria-hidden="true" tabindex="-1"></a> <span class="st">"500-1000"</span>,</span>
<span id="cb35-32"><a href="#cb35-32" aria-hidden="true" tabindex="-1"></a> <span class="st">"1000 - 2000"</span>,</span>
<span id="cb35-33"><a href="#cb35-33" aria-hidden="true" tabindex="-1"></a> <span class="st">"2000 - 4000"</span>,</span>
<span id="cb35-34"><a href="#cb35-34" aria-hidden="true" tabindex="-1"></a> <span class="st">"> 4000"</span></span>
<span id="cb35-35"><a href="#cb35-35" aria-hidden="true" tabindex="-1"></a> </span>
<span id="cb35-36"><a href="#cb35-36" aria-hidden="true" tabindex="-1"></a> )</span>
<span id="cb35-37"><a href="#cb35-37" aria-hidden="true" tabindex="-1"></a> ) <span class="sc">+</span></span>
<span id="cb35-38"><a href="#cb35-38" aria-hidden="true" tabindex="-1"></a> <span class="fu">labs</span>(</span>
<span id="cb35-39"><a href="#cb35-39" aria-hidden="true" tabindex="-1"></a> <span class="at">title =</span> <span class="st">"Elevation Map"</span>,</span>
<span id="cb35-40"><a href="#cb35-40" aria-hidden="true" tabindex="-1"></a> <span class="at">caption =</span> <span class="st">"Data Source: Natural Earth"</span></span>
<span id="cb35-41"><a href="#cb35-41" aria-hidden="true" tabindex="-1"></a> ) <span class="sc">+</span></span>
<span id="cb35-42"><a href="#cb35-42" aria-hidden="true" tabindex="-1"></a> <span class="co"># North arrow at top left</span></span>
<span id="cb35-43"><a href="#cb35-43" aria-hidden="true" tabindex="-1"></a> <span class="fu">coord_sf</span>(<span class="at">expand =</span> <span class="cn">FALSE</span>) <span class="sc">+</span> <span class="co"># Keep lat/lon ticks</span></span>
<span id="cb35-44"><a href="#cb35-44" aria-hidden="true" tabindex="-1"></a> <span class="fu">theme_minimal</span>(<span class="at">base_size =</span> <span class="dv">14</span>) <span class="sc">+</span> <span class="co"># Minimal theme with a clean design</span></span>
<span id="cb35-45"><a href="#cb35-45" aria-hidden="true" tabindex="-1"></a> <span class="fu">theme</span>(</span>
<span id="cb35-46"><a href="#cb35-46" aria-hidden="true" tabindex="-1"></a> <span class="at">legend.title =</span> <span class="fu">element_text</span>(<span class="at">size =</span> <span class="dv">12</span>),</span>
<span id="cb35-47"><a href="#cb35-47" aria-hidden="true" tabindex="-1"></a> <span class="at">legend.text =</span> <span class="fu">element_text</span>(<span class="at">size =</span> <span class="dv">10</span>),</span>
<span id="cb35-48"><a href="#cb35-48" aria-hidden="true" tabindex="-1"></a> <span class="at">axis.title =</span> <span class="fu">element_blank</span>(),</span>
<span id="cb35-49"><a href="#cb35-49" aria-hidden="true" tabindex="-1"></a> <span class="at">axis.text =</span> <span class="fu">element_blank</span>(),</span>
<span id="cb35-50"><a href="#cb35-50" aria-hidden="true" tabindex="-1"></a> <span class="at">plot.title =</span> <span class="fu">element_text</span>(<span class="at">size =</span> <span class="dv">16</span>, <span class="at">face =</span> <span class="st">"bold"</span>, <span class="at">hjust =</span> <span class="fl">0.5</span>),</span>
<span id="cb35-51"><a href="#cb35-51" aria-hidden="true" tabindex="-1"></a> <span class="at">plot.subtitle =</span> <span class="fu">element_text</span>(<span class="at">size =</span> <span class="dv">12</span>, <span class="at">hjust =</span> <span class="fl">0.5</span>),</span>
<span id="cb35-52"><a href="#cb35-52" aria-hidden="true" tabindex="-1"></a> <span class="at">plot.caption =</span> <span class="fu">element_text</span>(<span class="at">size =</span> <span class="dv">10</span>, <span class="at">hjust =</span> <span class="dv">1</span>)</span>
<span id="cb35-53"><a href="#cb35-53" aria-hidden="true" tabindex="-1"></a> )</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="r-spatial-data-and-mapping_files/figure-html/unnamed-chunk-26-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
<ul>
<li><code>geom_stars()</code> is used to plot raster data (elevation) where the fill color is based on the binned categories of elevation.</li>
<li><code>scale_fill_manual()</code> assigns specific colors to each elevation bin.</li>
<li><code>coord_sf(expand = FALSE)</code> ensures there is no padding around the map, keeping the focus on the data.</li>
<li>Customizing with <code>theme()</code> allows you to adjust text sizes, remove axis labels, and improve the overall look.</li>
</ul>
</section>
<section id="example-annual-precipitation-map" class="level3">
<h3 class="anchored" data-anchor-id="example-annual-precipitation-map">Example: Annual Precipitation Map</h3>
<p>Now let’s visualize precipitation data using WorldClim data, which is stored as a raster dataset.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb36"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(ggspatial)</span>
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a>geodata_path <span class="ot"><-</span> <span class="fu">file.path</span>(<span class="fu">getwd</span>(), <span class="st">"data"</span>)</span>
<span id="cb36-3"><a href="#cb36-3" aria-hidden="true" tabindex="-1"></a><span class="co"># Load the WorldClim precipitation data</span></span>
<span id="cb36-4"><a href="#cb36-4" aria-hidden="true" tabindex="-1"></a>prec <span class="ot"><-</span> <span class="fu">worldclim_global</span>(<span class="at">var =</span> <span class="st">"prec"</span>, <span class="at">res =</span> <span class="dv">10</span>, <span class="at">path =</span> geodata_path)</span>
<span id="cb36-5"><a href="#cb36-5" aria-hidden="true" tabindex="-1"></a>prec <span class="ot"><-</span> prec<span class="sc">$</span>wc2<span class="fl">.1</span>_10m_prec_01 <span class="sc">|></span> <span class="fu">st_as_stars</span>()</span>
<span id="cb36-6"><a href="#cb36-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-7"><a href="#cb36-7" aria-hidden="true" tabindex="-1"></a><span class="co"># Define breaks for precipitation (in mm) and custom blue color palette</span></span>
<span id="cb36-8"><a href="#cb36-8" aria-hidden="true" tabindex="-1"></a>brks <span class="ot"><-</span> <span class="fu">c</span>(<span class="dv">0</span>, <span class="dv">50</span>, <span class="dv">100</span>, <span class="dv">200</span>, <span class="dv">500</span>, <span class="dv">1000</span>)</span>
<span id="cb36-9"><a href="#cb36-9" aria-hidden="true" tabindex="-1"></a>clrs <span class="ot"><-</span> <span class="fu">colorRampPalette</span>(<span class="fu">c</span>(<span class="st">'white'</span>, <span class="st">'steelblue4'</span>))</span>
<span id="cb36-10"><a href="#cb36-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-11"><a href="#cb36-11" aria-hidden="true" tabindex="-1"></a><span class="co"># Convert the precipitation data to a factor with levels corresponding to the breaks</span></span>
<span id="cb36-12"><a href="#cb36-12" aria-hidden="true" tabindex="-1"></a>prec_factor <span class="ot"><-</span> <span class="fu">cut</span>(prec, <span class="at">breaks =</span> brks, <span class="at">include.lowest =</span> <span class="cn">TRUE</span>, <span class="at">labels =</span> <span class="fu">c</span>(<span class="st">"0-50"</span>, <span class="st">"50-100"</span>, <span class="st">"100-200"</span>, <span class="st">"200-500"</span>, <span class="st">"500-1000"</span>)) <span class="sc">|></span> <span class="fu">st_as_stars</span>()</span>
<span id="cb36-13"><a href="#cb36-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-14"><a href="#cb36-14" aria-hidden="true" tabindex="-1"></a><span class="co"># Create the plot</span></span>
<span id="cb36-15"><a href="#cb36-15" aria-hidden="true" tabindex="-1"></a><span class="fu">ggplot</span>() <span class="sc">+</span></span>
<span id="cb36-16"><a href="#cb36-16" aria-hidden="true" tabindex="-1"></a> <span class="fu">geom_stars</span>(<span class="at">data =</span> prec_factor) <span class="sc">+</span> <span class="co"># Use the factorized data for fill</span></span>
<span id="cb36-17"><a href="#cb36-17" aria-hidden="true" tabindex="-1"></a> <span class="fu">scale_fill_manual</span>(</span>
<span id="cb36-18"><a href="#cb36-18" aria-hidden="true" tabindex="-1"></a> <span class="at">values =</span> <span class="fu">clrs</span>(<span class="dv">5</span>), </span>
<span id="cb36-19"><a href="#cb36-19" aria-hidden="true" tabindex="-1"></a> <span class="at">name =</span> <span class="st">"Annual</span><span class="sc">\n</span><span class="st">Precipitation (mm)"</span>,</span>
<span id="cb36-20"><a href="#cb36-20" aria-hidden="true" tabindex="-1"></a> <span class="at">na.value =</span> <span class="st">"transparent"</span>) <span class="sc">+</span></span>
<span id="cb36-21"><a href="#cb36-21" aria-hidden="true" tabindex="-1"></a> <span class="fu">labs</span>(<span class="at">caption =</span> <span class="st">"Data Source: WorldClim"</span>) <span class="sc">+</span></span>
<span id="cb36-22"><a href="#cb36-22" aria-hidden="true" tabindex="-1"></a> <span class="co"># Overlay country boundaries</span></span>
<span id="cb36-23"><a href="#cb36-23" aria-hidden="true" tabindex="-1"></a> <span class="fu">geom_sf</span>(<span class="at">data =</span> oceans, <span class="at">fill =</span> <span class="st">"lightblue"</span>, <span class="at">color =</span> <span class="st">"steelblue"</span>, <span class="at">size =</span> <span class="fl">0.3</span>) <span class="sc">+</span></span>
<span id="cb36-24"><a href="#cb36-24" aria-hidden="true" tabindex="-1"></a> </span>
<span id="cb36-25"><a href="#cb36-25" aria-hidden="true" tabindex="-1"></a> <span class="fu">coord_sf</span>(<span class="at">crs =</span> <span class="dv">4326</span>) <span class="sc">+</span></span>
<span id="cb36-26"><a href="#cb36-26" aria-hidden="true" tabindex="-1"></a> <span class="co">#annotation_north_arrow(height = unit(0.6, "cm"),width = unit(0.6, "cm"))+</span></span>
<span id="cb36-27"><a href="#cb36-27" aria-hidden="true" tabindex="-1"></a> <span class="co">#annotation_scale(height = unit(0.2,"cm"), location = "br", unit_category = "metric")+</span></span>
<span id="cb36-28"><a href="#cb36-28" aria-hidden="true" tabindex="-1"></a> <span class="fu">theme_minimal</span>()<span class="sc">+</span></span>
<span id="cb36-29"><a href="#cb36-29" aria-hidden="true" tabindex="-1"></a> <span class="fu">theme</span>(</span>
<span id="cb36-30"><a href="#cb36-30" aria-hidden="true" tabindex="-1"></a> <span class="at">legend.title =</span> <span class="fu">element_text</span>(<span class="at">size =</span> <span class="dv">8</span>),</span>
<span id="cb36-31"><a href="#cb36-31" aria-hidden="true" tabindex="-1"></a> <span class="at">legend.text =</span> <span class="fu">element_text</span>(<span class="at">size =</span> <span class="dv">7</span>), </span>
<span id="cb36-32"><a href="#cb36-32" aria-hidden="true" tabindex="-1"></a> <span class="at">axis.title =</span> <span class="fu">element_blank</span>(),</span>
<span id="cb36-33"><a href="#cb36-33" aria-hidden="true" tabindex="-1"></a> <span class="at">axis.text =</span> <span class="fu">element_blank</span>())</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="r-spatial-data-and-mapping_files/figure-html/unnamed-chunk-27-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="going-beyond" class="level3">
<h3 class="anchored" data-anchor-id="going-beyond"><strong>Going Beyond</strong></h3>
<p>With these basics, you can start customizing maps further, like adding annotations, legends, north arrows, or even combining multiple spatial layers for more complex visualizations.</p>
<p>You can go completely crazy and create maps like below:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="images/crazy_swiss_map_with_crazy_legend.png" class="img-fluid figure-img"></p>
<figcaption>Map of Switzerland using ggplot2</figcaption>
</figure>
</div>
</section>
</section>
<section id="how-to-make-pretty-maps-with-tmap" class="level2">
<h2 class="anchored" data-anchor-id="how-to-make-pretty-maps-with-tmap"><strong>How to make pretty maps with tmap</strong></h2>
<div class="cell">
<div class="sourceCode cell-code" id="cb37"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(tmap)</span>
<span id="cb37-2"><a href="#cb37-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-3"><a href="#cb37-3" aria-hidden="true" tabindex="-1"></a><span class="co"># Define breaks for precipitation (in mm) and custom blue color palette</span></span>
<span id="cb37-4"><a href="#cb37-4" aria-hidden="true" tabindex="-1"></a>brks <span class="ot"><-</span> <span class="fu">c</span>(<span class="dv">0</span>, <span class="dv">50</span>, <span class="dv">100</span>, <span class="dv">200</span>, <span class="dv">500</span>, <span class="dv">1000</span>)</span>
<span id="cb37-5"><a href="#cb37-5" aria-hidden="true" tabindex="-1"></a>clrs <span class="ot"><-</span> <span class="fu">colorRampPalette</span>(<span class="fu">c</span>(<span class="st">'white'</span>, <span class="st">'steelblue4'</span>))(<span class="fu">length</span>(brks) <span class="sc">-</span> <span class="dv">1</span>)</span>
<span id="cb37-6"><a href="#cb37-6" aria-hidden="true" tabindex="-1"></a><span class="co"># Create the tmap plot</span></span>
<span id="cb37-7"><a href="#cb37-7" aria-hidden="true" tabindex="-1"></a><span class="fu">tm_shape</span>(prec_factor) <span class="sc">+</span></span>
<span id="cb37-8"><a href="#cb37-8" aria-hidden="true" tabindex="-1"></a> <span class="fu">tm_raster</span>(<span class="at">col.scale =</span> <span class="fu">tm_scale</span>(<span class="at">values =</span> clrs, <span class="at">breaks =</span> brks), </span>
<span id="cb37-9"><a href="#cb37-9" aria-hidden="true" tabindex="-1"></a> <span class="at">col.legend =</span> <span class="fu">tm_legend</span>(<span class="at">title =</span> <span class="st">"Precipitation (mm)"</span>, <span class="at">labels =</span> <span class="fu">levels</span>(prec_factor[[<span class="dv">1</span>]]))) <span class="sc">+</span></span>
<span id="cb37-10"><a href="#cb37-10" aria-hidden="true" tabindex="-1"></a> <span class="fu">tm_shape</span>(oceans) <span class="sc">+</span></span>
<span id="cb37-11"><a href="#cb37-11" aria-hidden="true" tabindex="-1"></a> <span class="fu">tm_polygons</span>(<span class="at">col =</span> <span class="st">"lightblue"</span>, <span class="at">border.col =</span> <span class="st">"steelblue"</span>) <span class="sc">+</span></span>
<span id="cb37-12"><a href="#cb37-12" aria-hidden="true" tabindex="-1"></a> <span class="fu">tm_scalebar</span>(<span class="at">position =</span> <span class="fu">c</span>(<span class="st">"right"</span>, <span class="st">"bottom"</span>)) <span class="sc">+</span> <span class="co"># Updated function name</span></span>
<span id="cb37-13"><a href="#cb37-13" aria-hidden="true" tabindex="-1"></a> <span class="fu">tm_compass</span>(<span class="at">position =</span> <span class="fu">c</span>(<span class="st">"left"</span>, <span class="st">"top"</span>), <span class="at">size =</span> <span class="dv">2</span>) <span class="sc">+</span></span>
<span id="cb37-14"><a href="#cb37-14" aria-hidden="true" tabindex="-1"></a> <span class="fu">tm_graticules</span>(<span class="at">col =</span> <span class="st">"steelblue3"</span>, <span class="at">alpha =</span> <span class="fl">0.3</span>) <span class="sc">+</span></span>
<span id="cb37-15"><a href="#cb37-15" aria-hidden="true" tabindex="-1"></a> <span class="fu">tm_layout</span>(</span>
<span id="cb37-16"><a href="#cb37-16" aria-hidden="true" tabindex="-1"></a> <span class="at">legend.position =</span> <span class="fu">c</span>(<span class="st">"LEFT"</span>, <span class="st">"BOTTOM"</span>), </span>
<span id="cb37-17"><a href="#cb37-17" aria-hidden="true" tabindex="-1"></a> <span class="at">legend.frame =</span> <span class="cn">FALSE</span>,</span>
<span id="cb37-18"><a href="#cb37-18" aria-hidden="true" tabindex="-1"></a> <span class="at">frame =</span> <span class="cn">FALSE</span>,</span>
<span id="cb37-19"><a href="#cb37-19" aria-hidden="true" tabindex="-1"></a> <span class="at">bg.color =</span> <span class="st">"gray95"</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="r-spatial-data-and-mapping_files/figure-html/unnamed-chunk-28-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
<div class="cell">
<div class="sourceCode cell-code" id="cb38"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Create the map</span></span>
<span id="cb38-2"><a href="#cb38-2" aria-hidden="true" tabindex="-1"></a><span class="fu">tm_shape</span>(countries) <span class="sc">+</span></span>
<span id="cb38-3"><a href="#cb38-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">tm_polygons</span>(</span>
<span id="cb38-4"><a href="#cb38-4" aria-hidden="true" tabindex="-1"></a> <span class="at">col =</span> <span class="st">"pop_class"</span>, <span class="co"># Fill polygons based on the pop_class column</span></span>
<span id="cb38-5"><a href="#cb38-5" aria-hidden="true" tabindex="-1"></a> <span class="at">palette =</span> <span class="fu">c</span>(<span class="st">"<1M"</span> <span class="ot">=</span> <span class="st">"#ffffff"</span>, <span class="st">"1-10M"</span> <span class="ot">=</span> <span class="st">"#fee5d9"</span>, <span class="st">"10-50M"</span> <span class="ot">=</span> <span class="st">"#fcae91"</span>,<span class="st">"50-200M"</span> <span class="ot">=</span> <span class="st">"#fb6a4a"</span>, <span class="st">"200M-1B"</span> <span class="ot">=</span> <span class="st">"#de2d26"</span>, <span class="st">">1B"</span> <span class="ot">=</span> <span class="st">"#a50f15"</span>),</span>
<span id="cb38-6"><a href="#cb38-6" aria-hidden="true" tabindex="-1"></a> <span class="at">title =</span> <span class="st">"Population"</span>, <span class="co"># Set title for the fill legend</span></span>
<span id="cb38-7"><a href="#cb38-7" aria-hidden="true" tabindex="-1"></a> <span class="at">border.alpha =</span> <span class="fl">0.2</span> <span class="co"># Remove the borders of the polygons</span></span>
<span id="cb38-8"><a href="#cb38-8" aria-hidden="true" tabindex="-1"></a> ) <span class="sc">+</span></span>
<span id="cb38-9"><a href="#cb38-9" aria-hidden="true" tabindex="-1"></a> <span class="fu">tm_scale_bar</span>(<span class="at">position =</span> <span class="fu">c</span>(<span class="st">"right"</span>, <span class="st">"bottom"</span>)) <span class="sc">+</span> <span class="co"># Add scale bar</span></span>
<span id="cb38-10"><a href="#cb38-10" aria-hidden="true" tabindex="-1"></a> <span class="fu">tm_compass</span>(<span class="at">position =</span> <span class="fu">c</span>(<span class="st">"left"</span>, <span class="st">"top"</span>), <span class="at">size =</span> <span class="dv">2</span>) <span class="sc">+</span> <span class="co"># Add compass</span></span>
<span id="cb38-11"><a href="#cb38-11" aria-hidden="true" tabindex="-1"></a> <span class="fu">tm_graticules</span>(<span class="at">col =</span> <span class="st">"gray80"</span>, <span class="at">alpha =</span> <span class="fl">0.3</span>) <span class="sc">+</span> <span class="co"># Add graticules with light color</span></span>
<span id="cb38-12"><a href="#cb38-12" aria-hidden="true" tabindex="-1"></a> <span class="fu">tm_layout</span>(</span>
<span id="cb38-13"><a href="#cb38-13" aria-hidden="true" tabindex="-1"></a> <span class="at">legend.position =</span> <span class="fu">c</span>(<span class="st">"LEFT"</span>, <span class="st">"BOTTOM"</span>),</span>
<span id="cb38-14"><a href="#cb38-14" aria-hidden="true" tabindex="-1"></a> <span class="at">legend.frame =</span> <span class="cn">FALSE</span>, </span>
<span id="cb38-15"><a href="#cb38-15" aria-hidden="true" tabindex="-1"></a> <span class="at">frame =</span> <span class="cn">FALSE</span>,</span>
<span id="cb38-16"><a href="#cb38-16" aria-hidden="true" tabindex="-1"></a> <span class="at">bg.color =</span> <span class="st">"gray95"</span> </span>
<span id="cb38-17"><a href="#cb38-17" aria-hidden="true" tabindex="-1"></a> )</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="r-spatial-data-and-mapping_files/figure-html/unnamed-chunk-29-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
</section>
</section>
</main>
<!-- /main column -->
<script id="quarto-html-after-body" type="application/javascript">
window.document.addEventListener("DOMContentLoaded", function (event) {
const toggleBodyColorMode = (bsSheetEl) => {
const mode = bsSheetEl.getAttribute("data-mode");
const bodyEl = window.document.querySelector("body");
if (mode === "dark") {
bodyEl.classList.add("quarto-dark");
bodyEl.classList.remove("quarto-light");
} else {
bodyEl.classList.add("quarto-light");
bodyEl.classList.remove("quarto-dark");
}
}
const toggleBodyColorPrimary = () => {
const bsSheetEl = window.document.querySelector("link#quarto-bootstrap");
if (bsSheetEl) {
toggleBodyColorMode(bsSheetEl);
}
}
toggleBodyColorPrimary();
const icon = "";
const anchorJS = new window.AnchorJS();
anchorJS.options = {
placement: 'right',
icon: icon
};
anchorJS.add('.anchored');
const isCodeAnnotation = (el) => {
for (const clz of el.classList) {
if (clz.startsWith('code-annotation-')) {
return true;
}
}
return false;
}
const onCopySuccess = function(e) {
// button target
const button = e.trigger;
// don't keep focus
button.blur();
// flash "checked"
button.classList.add('code-copy-button-checked');
var currentTitle = button.getAttribute("title");
button.setAttribute("title", "Copied!");
let tooltip;
if (window.bootstrap) {
button.setAttribute("data-bs-toggle", "tooltip");
button.setAttribute("data-bs-placement", "left");
button.setAttribute("data-bs-title", "Copied!");
tooltip = new bootstrap.Tooltip(button,
{ trigger: "manual",
customClass: "code-copy-button-tooltip",
offset: [0, -8]});
tooltip.show();
}
setTimeout(function() {
if (tooltip) {
tooltip.hide();
button.removeAttribute("data-bs-title");
button.removeAttribute("data-bs-toggle");
button.removeAttribute("data-bs-placement");
}
button.setAttribute("title", currentTitle);
button.classList.remove('code-copy-button-checked');
}, 1000);
// clear code selection
e.clearSelection();
}
const getTextToCopy = function(trigger) {
const codeEl = trigger.previousElementSibling.cloneNode(true);
for (const childEl of codeEl.children) {
if (isCodeAnnotation(childEl)) {
childEl.remove();
}
}
return codeEl.innerText;
}
const clipboard = new window.ClipboardJS('.code-copy-button:not([data-in-quarto-modal])', {
text: getTextToCopy
});
clipboard.on('success', onCopySuccess);
if (window.document.getElementById('quarto-embedded-source-code-modal')) {
// For code content inside modals, clipBoardJS needs to be initialized with a container option
// TODO: Check when it could be a function (https://github.com/zenorocha/clipboard.js/issues/860)