class: center, middle, inverse, title-slide # Geospatial Techniques for Social Scientists in R ## Raster Data ### Stefan Jünger & Anne-Kathrin Stroppe
February 08, 2021 --- layout: true --- ## Now <table class="table" style="margin-left: auto; margin-right: auto;"> <thead> <tr> <th style="text-align:left;"> Day </th> <th style="text-align:left;"> Time </th> <th style="text-align:left;"> Title </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;color: gray !important;"> February 08 </td> <td style="text-align:left;color: gray !important;"> 09:00am-10:30am </td> <td style="text-align:left;font-weight: bold;"> Introduction </td> </tr> <tr> <td style="text-align:left;color: gray !important;"> February 08 </td> <td style="text-align:left;color: gray !important;"> 11:00am-12:30pm </td> <td style="text-align:left;font-weight: bold;"> Vector Data </td> </tr> <tr> <td style="text-align:left;color: gray !important;color: gray !important;"> February 08 </td> <td style="text-align:left;color: gray !important;color: gray !important;"> 12:30pm-01:30pm </td> <td style="text-align:left;font-weight: bold;color: gray !important;"> Lunch Break </td> </tr> <tr> <td style="text-align:left;color: gray !important;"> February 08 </td> <td style="text-align:left;color: gray !important;"> 01:30pm-03:00pm </td> <td style="text-align:left;font-weight: bold;"> Basic Maps </td> </tr> <tr> <td style="text-align:left;color: gray !important;border-bottom: 1px solidbackground-color: yellow !important;"> February 08 </td> <td style="text-align:left;color: gray !important;border-bottom: 1px solidbackground-color: yellow !important;"> 03:30pm-05:00pm </td> <td style="text-align:left;font-weight: bold;border-bottom: 1px solidbackground-color: yellow !important;"> Raster Data </td> </tr> <tr> <td style="text-align:left;color: gray !important;"> February 09 </td> <td style="text-align:left;color: gray !important;"> 09:00am-10:30am </td> <td style="text-align:left;font-weight: bold;"> Advanced Data Import </td> </tr> <tr> <td style="text-align:left;color: gray !important;"> February 09 </td> <td style="text-align:left;color: gray !important;"> 11:00am-12:30pm </td> <td style="text-align:left;font-weight: bold;"> Applied Data Wrangling </td> </tr> <tr> <td style="text-align:left;color: gray !important;color: gray !important;"> February 09 </td> <td style="text-align:left;color: gray !important;color: gray !important;"> 12:30pm-13:30pm </td> <td style="text-align:left;font-weight: bold;color: gray !important;"> Lunch Break </td> </tr> <tr> <td style="text-align:left;color: gray !important;"> February 09 </td> <td style="text-align:left;color: gray !important;"> 01:30pm-03:00pm </td> <td style="text-align:left;font-weight: bold;"> Advanced Maps I </td> </tr> <tr> <td style="text-align:left;color: gray !important;"> February 09 </td> <td style="text-align:left;color: gray !important;"> 03:30pm-05:00pm </td> <td style="text-align:left;font-weight: bold;"> Advanced Maps II </td> </tr> </tbody> </table> --- ## `R`-Packages *We* Will Use - `raster` - still the major workhorse for raster data - there's a successor: `terra` package, but it's still in development - `stars` - interface to modern geospatial data implementations, most and foremost from `sf` - package for spatiotemporal datacubes and non-regular raster grids (more on that at the end of the session) - we will use it only as a supportive package for specific purposes --- ## General Difference to Vector Data Data Structure: - Other data format(s) - geometries do not differ within one dataset - sometimes smaller, sometimes larger... Implications: - Other geospatial operations possible - can be way more efficient Benefits: - straightforward processing of raster values and extraction of zonal statistics - it's like working with simple tabular data --- ## Visual Difference Between Vector and Raster Data <img src="data:image/png;base64,#./img/fig_geometries.png" width="40%" style="display: block; margin: auto;" /> --- ## What Exactly Are Raster Data? - Hold information on (most of the time) evenly shaped grid cells - Basically, a simple data table - each cell represents one observation <img src="data:image/png;base64,#./img/table_to_raster.png" width="5333" style="display: block; margin: auto;" /> --- ## Metadata - Information about geometries are globally stored as they are the same for all observation - their location in space is defined by their cell location in the data table - Without this information, raster data are simple image files --- ## Important Metadata - Raster Dimensions - number of columns, rows, and cells - Extent - Similar to bounding box in vector data - Resolution - size of each raster cell - Coordinate reference system - defines where on earth's surface the raster layer lies --- ## All Beginnings Are... Easy! ```r raster::raster() ``` ``` ## class : RasterLayer ## dimensions : 180, 360, 64800 (nrow, ncol, ncell) ## resolution : 1, 1 (x, y) ## extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax) ## crs : +proj=longlat +datum=WGS84 +no_defs ``` --- ## Feed With Data ```r input_data <- sample(1:100, 16) %>% matrix(nrow = 4) raster_layer <- raster::raster(input_data) raster_layer ``` ``` ## class : RasterLayer ## dimensions : 4, 4, 16 (nrow, ncol, ncell) ## resolution : 0.25, 0.25 (x, y) ## extent : 0, 1, 0, 1 (xmin, xmax, ymin, ymax) ## crs : NA ## source : memory ## names : layer ## values : 22, 90 (min, max) ``` --- ## Plotting ```r raster::plot(raster_layer) ``` <img src="data:image/png;base64,#1_4_Raster_Data_files/figure-html/plot-raster-1.png" width="60%" style="display: block; margin: auto;" /> --- ## File Formats - Gtiff/GeoTiff - JPEG2000 - ... - .grd - netCDF - ... - sometimes, raster data come even in a text format, such as CSV **In this course, we will only use `tiff` files as it is pretty common. Just be aware that there a different formats out there.** --- ## Implementations in `R` Again, `raster` is the most commonly used package for raster data in `R`. Some newer developments, e.g., as in the `stars` package, also implement an interface to simple features in `sf`. The `terra` package helps use more elaborate zonal statistics. The same holds for the `spatstat` package. --- class: middle ## Basic Raster Operations --- ## Loading Raster Tiffs (Census Data) ```r immigrants_cologne <- raster::raster("../../data/immigrants_cologne.tif") inhabitants_cologne <- raster::raster("../../data/inhabitants_cologne.tif") immigrants_cologne ``` ``` ## class : RasterLayer ## dimensions : 289, 264, 76296 (nrow, ncol, ncell) ## resolution : 100, 100 (x, y) ## extent : 4094850, 4121250, 3084050, 3112950 (xmin, xmax, ymin, ymax) ## crs : +proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000 +ellps=GRS80 +units=m +no_defs ## source : C:/Users/mueller2/talks_presentations/gesis-workshop-geospatial-techniques-R/data/immigrants_cologne.tif ## names : immigrants_cologne ## values : 3, 639 (min, max) ``` ```r inhabitants_cologne ``` ``` ## class : RasterLayer ## dimensions : 289, 264, 76296 (nrow, ncol, ncell) ## resolution : 100, 100 (x, y) ## extent : 4094850, 4121250, 3084050, 3112950 (xmin, xmax, ymin, ymax) ## crs : +proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000 +ellps=GRS80 +units=m +no_defs ## source : C:/Users/mueller2/talks_presentations/gesis-workshop-geospatial-techniques-R/data/inhabitants_cologne.tif ## names : inhabitants_cologne ## values : 3, 956 (min, max) ``` --- ## Compare Layers by Plotting .pull-left[ ```r raster::plot(immigrants_cologne) ``` <img src="data:image/png;base64,#1_4_Raster_Data_files/figure-html/plot-immigrants-1.png" style="display: block; margin: auto;" /> ] .pull-right[ ```r raster::plot(inhabitants_cologne) ``` <img src="data:image/png;base64,#1_4_Raster_Data_files/figure-html/plot-inhabitants-1.png" style="display: block; margin: auto;" /> ] --- ## Btw: We Can Also Use `tmap` .pull-left[ ```r tm_shape(immigrants_cologne) + tm_raster() ``` <img src="data:image/png;base64,#1_4_Raster_Data_files/figure-html/plot-immigrants-tmap-1.png" style="display: block; margin: auto;" /> ] .pull-right[ ```r tm_shape(inhabitants_cologne) + tm_raster() ``` <img src="data:image/png;base64,#1_4_Raster_Data_files/figure-html/plot-inhabitants-tmap-1.png" style="display: block; margin: auto;" /> ] --- ## Preparing for Analysis / Base `R` Functionalities ```r immigrants_cologne[immigrants_cologne == -9] <- NA inhabitants_cologne[inhabitants_cologne == -9] <- NA immigrants_cologne ``` ``` ## class : RasterLayer ## dimensions : 289, 264, 76296 (nrow, ncol, ncell) ## resolution : 100, 100 (x, y) ## extent : 4094850, 4121250, 3084050, 3112950 (xmin, xmax, ymin, ymax) ## crs : +proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000 +ellps=GRS80 +units=m +no_defs ## source : memory ## names : immigrants_cologne ## values : 3, 639 (min, max) ``` ```r inhabitants_cologne ``` ``` ## class : RasterLayer ## dimensions : 289, 264, 76296 (nrow, ncol, ncell) ## resolution : 100, 100 (x, y) ## extent : 4094850, 4121250, 3084050, 3112950 (xmin, xmax, ymin, ymax) ## crs : +proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000 +ellps=GRS80 +units=m +no_defs ## source : memory ## names : inhabitants_cologne ## values : 3, 956 (min, max) ``` --- ## Simple Statistics Working with raster data is straightforward - quite speedy - yet not as comfortable as working with `sf` objects For example, to calculate the mean we would use: ```r raster::cellStats(immigrants_cologne, stat = "mean") ``` ``` ## [1] 15.1337 ``` --- ## Get All Values As a Vector We can also extract the values of a raster directly as vector: ```r all_raster_values <- raster::values(immigrants_cologne) mean(all_raster_values, na.rm = TRUE) ``` ``` ## [1] 15.1337 ``` Nevertheless, although raster data are simple data tables, working with them is a bit different compared to, e.g., simple features. --- ## Combining Raster Layers to Calculate New Values .pull-left[ ```r immigrant_rate <- immigrants_cologne * 100 / inhabitants_cologne immigrant_rate ``` ``` ## class : RasterLayer ## dimensions : 289, 264, 76296 (nrow, ncol, ncell) ## resolution : 100, 100 (x, y) ## extent : 4094850, 4121250, 3084050, 3112950 (xmin, xmax, ymin, ymax) ## crs : +proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000 +ellps=GRS80 +units=m +no_defs ## source : memory ## names : layer ## values : 0.6637168, 100 (min, max) ``` ] -- .pull-right[ <img src="data:image/png;base64,#1_4_Raster_Data_files/figure-html/combined-raster-plot-1.png" style="display: block; margin: auto;" /> ] --- ## 'Subsetting' Raster Layers We can subsetting vector data by simply filtering for specific attribute values. For example, to subset Cologne's districts only by the one of Deutz we can use the Tidyverse for `sf` data: .pull-left[ ```r deutz <- sf::st_read("../../data/cologne.shp") %>% dplyr::filter(NAME == "Deutz") ``` ``` ## Reading layer `cologne' from data source `C:\Users\mueller2\talks_presentations\gesis-workshop-geospatial-techniques-R\data\cologne.shp' using driver `ESRI Shapefile' ## Simple feature collection with 86 features and 7 fields ## geometry type: MULTIPOLYGON ## dimension: XY ## bbox: xmin: 4094821 ymin: 3084022 xmax: 4121277 ymax: 3112952 ## projected CRS: ETRS89-extended / LAEA Europe ``` ] .pull-right[ <img src="data:image/png;base64,#1_4_Raster_Data_files/figure-html/plot-deutz-1.png" style="display: block; margin: auto;" /> ] --- ## Cropping Cropping is a method of cutting out a specific `slice` of a raster layer based on an input dataset or geospatial extent, such as a bounding box. -- .pull-left[ ```r cropped_immigrant_rate <- raster::crop(immigrant_rate, deutz) ``` ] -- .pull-right[ <img src="data:image/png;base64,#1_4_Raster_Data_files/figure-html/crop-raster-map-1.png" style="display: block; margin: auto;" /> ] --- ## Masking Masking is similar to cropping, yet values outside the extent just get set to missing values (`NA`). -- .pull-left[ ```r masked_immigrant_rate <- raster::mask(immigrant_rate, deutz) ``` ] -- .pull-right[ <img src="data:image/png;base64,#1_4_Raster_Data_files/figure-html/mask-raster-map-1.png" style="display: block; margin: auto;" /> ] --- class: middle ## Exercise 1_4_1: Basic Raster Operations [Exercise](https://stefanjuenger.github.io/gesis-workshop-geospatial-techniques-R/exercises/1_4_1_Basic_Raster_Operations_question.html) [Solution](https://stefanjuenger.github.io/gesis-workshop-geospatial-techniques-R/solutions/1_4_1_Basic_Raster_Operations_solution.html) --- class: middle ## Raster Extraction / Zonal statistics --- ## Sampling of some points .pull-left[ ```r fancy_points <- immigrants_cologne %>% stars::st_as_stars() %>% sf::st_as_sf() %>% sf::st_sample(10) %>% sf::st_as_sf() ``` ] -- .pull-right[ ```r plot(fancy_points) ``` <img src="data:image/png;base64,#1_4_Raster_Data_files/figure-html/plot-fancy-points-1.png" style="display: block; margin: auto;" /> ] --- ## Extract Information From Rasters .pull-left[ Raster data are useful when we aim to - apply calculations that are the same for all geometries in the dataset - **extract information from raster fast and efficient** ] .pull-right[ ```r tm_shape(immigrant_rate) + tm_raster() + tm_shape(fancy_points) + tm_dots(size = .25) ``` <img src="data:image/png;base64,#1_4_Raster_Data_files/figure-html/plot-raster-extraction-1.png" style="display: block; margin: auto;" /> ] --- ## Raster Extraction To extract the raster values at a specific point by location we simply use: ```r raster::extract(immigrants_cologne, fancy_points) ``` ``` ## [1] 6 4 3 7 3 4 3 3 11 4 ``` --- ## Add Results to Existing Dataset (More on That Tomorrow) These information can simply be added to an existing dataset (our points in this example): ```r fancy_points <- fancy_points %>% dplyr::bind_cols( immigrant_rate_value = raster::extract(immigrant_rate, .) ) fancy_points ``` ``` ## Simple feature collection with 10 features and 1 field ## geometry type: POINT ## dimension: XY ## bbox: xmin: 4098242 ymin: 3086112 xmax: 4117484 ymax: 3107657 ## CRS: +proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000 +ellps=GRS80 +units=m +no_defs ## immigrant_rate_value x ## 1 13.333333 POINT (4117484 3101857) ## 2 8.333333 POINT (4098242 3097630) ## 3 6.818182 POINT (4114385 3095502) ## 4 4.861111 POINT (4104897 3098393) ## 5 3.571429 POINT (4111528 3091517) ## 6 12.500000 POINT (4101958 3098364) ## 7 3.333333 POINT (4103515 3095113) ## 8 6.521739 POINT (4116339 3086112) ## 9 9.016393 POINT (4110697 3107657) ## 10 10.810811 POINT (4104073 3092852) ``` --- ## More Elaborated: Spatial Buffers .pull-left[ Sometimes extracting information 1:1 is not enough - too narrow - missing information about the surrounding of a point in space ] .pull-right[ ```r tm_shape(immigrants_cologne) + tm_raster() + tm_shape( fancy_points %>% sf::st_buffer(500) ) + tm_dots(size = .1) + tm_borders() ``` <img src="data:image/png;base64,#1_4_Raster_Data_files/figure-html/plot-buffer-extraction-1.png" width="75%" style="display: block; margin: auto;" /> ] --- ## Buffer Extraction Wa can use spatial buffers of different sizes to extract information on surroundings: ```r raster::extract( immigrants_cologne, fancy_points, buffer = 500, fun = mean ) ``` ``` ## [1] 9.000000 6.265306 30.641026 17.205882 7.545455 6.171429 8.075472 ## [8] 5.235294 8.324324 7.750000 ``` --- ## Focal Statistics Focal statistics are another method of include information in the proximity of a point in space. However, it's applied to the whole dataset and is independent of arbitrary points we project onto a map. - relates focal cells to surrounding cells - vastly used in image processing - but also applicable in social science research as we will see --- ## Focal Application: Edge Detection .pull-left[ <img src="data:image/png;base64,#./img/Bikesgray.jpg" width="853" style="display: block; margin: auto;" /> ] .pull-right[ <img src="data:image/png;base64,#./img/Bikesgraysobel.jpg" width="853" style="display: block; margin: auto;" /> ] .tinyisher[Source: https://en.wikipedia.org/wiki/Sobel_operator] --- ## Edges of Immigrant Rates <img src="data:image/png;base64,#./img/legewie_schaeffer_2016.png" width="2797" style="display: block; margin: auto;" /> --- ## We Can Do That As Well Using a Sobel Filter `$$r_x = \begin{bmatrix}1 & 0 & -1 \\2 & 0 & -2 \\1 & 0 & -1\end{bmatrix} \times raster\_file \\r_y = \begin{bmatrix}1 & 2 & 1 \\0 & 0 & 0 \\-1 & -2 & -1\end{bmatrix}\times raster\_file \\r_{xy} = \sqrt{r_{x}^2 + r_{y}^2}$$` --- ## Implementation in R From the [official documentation](http://search.r-project.org/R/library/raster/html/focal.html): ```r sobel <- function(r) { fy <- matrix(c(1, 0, -1, 2, 0, -2, 1, 0, -1), nrow = 3) fx <- matrix(c(-1, -2, -1, 0, 0, 0, 1, 2, 1) , nrow = 3) rx <- focal(r, fx) ry <- focal(r, fy) sqrt(rx^2 + ry^2) } ``` --- ## Data Preparation and Application of Filter ```r old_extent <- raster::extent(immigrant_rate) new_extent <- old_extent + c(10000, -10000, 10000, -10000) smaller_immigrant_rate <- immigrant_rate %>% raster::crop(new_extent) smaller_immigrant_rate[smaller_immigrant_rate < 15] <- NA immigrant_edges <- sobel(smaller_immigrant_rate) ``` --- ## Comparison .pull-left[ <img src="data:image/png;base64,#1_4_Raster_Data_files/figure-html/original-image-1.png" style="display: block; margin: auto;" /> ] -- .pull-right[ <img src="data:image/png;base64,#1_4_Raster_Data_files/figure-html/sobel-image-1.png" style="display: block; margin: auto;" /> ] --- class: middle ## Exercise 1_4_2: : Fancier Raster Operations [Exercise](https://stefanjuenger.github.io/gesis-workshop-geospatial-techniques-R/exercises/1_4_2_Fancier_Raster_Operations_question.html) [Solution](https://stefanjuenger.github.io/gesis-workshop-geospatial-techniques-R/solutions/1_4_2_Fancier_Raster_Operations_solution.html) --- ## Raster Stacks (Or `raster::brick()`, Respectively) So far, raster data have been unidimensional: we only had one attribute for each dataset. But they can also be stacked: ```r census_stack <- raster::stack(immigrants_cologne, inhabitants_cologne) census_stack ``` ``` ## class : RasterStack ## dimensions : 289, 264, 76296, 2 (nrow, ncol, ncell, nlayers) ## resolution : 100, 100 (x, y) ## extent : 4094850, 4121250, 3084050, 3112950 (xmin, xmax, ymin, ymax) ## crs : +proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000 +ellps=GRS80 +units=m +no_defs ## names : immigrants_cologne, inhabitants_cologne ## min values : 3, 3 ## max values : 639, 956 ``` --- ## Multi-Band Rasters .pull-left[ ```r germans_cologne <- raster::raster( "../../data/germans_cologne.tif" ) census_rg <- raster::stack( germans_cologne, immigrants_cologne ) ``` ] .pull-right[ ```r raster::plotRGB( census_rg, scale = 639, stretch = "lin" ) ``` <img src="data:image/png;base64,#1_4_Raster_Data_files/figure-html/rg-layer-plot-1.png" width="75%" style="display: block; margin: auto;" /> ] --- ## Non-Regular Grids In this course, we will only use regular grid-based raster data. But be aware that also non-regular grid data exist. <img src="data:image/png;base64,#./img/nonregular_grid.png" width="80%" style="display: block; margin: auto;" /> .tinyisher[Source: https://r-spatial.github.io/stars/] --- ## Tomorrow <table class="table" style="margin-left: auto; margin-right: auto;"> <thead> <tr> <th style="text-align:left;"> Day </th> <th style="text-align:left;"> Time </th> <th style="text-align:left;"> Title </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;color: gray !important;"> February 08 </td> <td style="text-align:left;color: gray !important;"> 09:00am-10:30am </td> <td style="text-align:left;font-weight: bold;"> Introduction </td> </tr> <tr> <td style="text-align:left;color: gray !important;"> February 08 </td> <td style="text-align:left;color: gray !important;"> 11:00am-12:30pm </td> <td style="text-align:left;font-weight: bold;"> Vector Data </td> </tr> <tr> <td style="text-align:left;color: gray !important;color: gray !important;"> February 08 </td> <td style="text-align:left;color: gray !important;color: gray !important;"> 12:30pm-01:30pm </td> <td style="text-align:left;font-weight: bold;color: gray !important;"> Lunch Break </td> </tr> <tr> <td style="text-align:left;color: gray !important;"> February 08 </td> <td style="text-align:left;color: gray !important;"> 01:30pm-03:00pm </td> <td style="text-align:left;font-weight: bold;"> Basic Maps </td> </tr> <tr> <td style="text-align:left;color: gray !important;border-bottom: 1px solid"> February 08 </td> <td style="text-align:left;color: gray !important;border-bottom: 1px solid"> 03:30pm-05:00pm </td> <td style="text-align:left;font-weight: bold;border-bottom: 1px solid"> Raster Data </td> </tr> <tr> <td style="text-align:left;color: gray !important;background-color: yellow !important;"> February 09 </td> <td style="text-align:left;color: gray !important;background-color: yellow !important;"> 09:00am-10:30am </td> <td style="text-align:left;font-weight: bold;background-color: yellow !important;"> Advanced Data Import </td> </tr> <tr> <td style="text-align:left;color: gray !important;background-color: yellow !important;"> February 09 </td> <td style="text-align:left;color: gray !important;background-color: yellow !important;"> 11:00am-12:30pm </td> <td style="text-align:left;font-weight: bold;background-color: yellow !important;"> Applied Data Wrangling </td> </tr> <tr> <td style="text-align:left;color: gray !important;color: gray !important;background-color: yellow !important;"> February 09 </td> <td style="text-align:left;color: gray !important;color: gray !important;background-color: yellow !important;"> 12:30pm-13:30pm </td> <td style="text-align:left;font-weight: bold;color: gray !important;background-color: yellow !important;"> Lunch Break </td> </tr> <tr> <td style="text-align:left;color: gray !important;background-color: yellow !important;"> February 09 </td> <td style="text-align:left;color: gray !important;background-color: yellow !important;"> 01:30pm-03:00pm </td> <td style="text-align:left;font-weight: bold;background-color: yellow !important;"> Advanced Maps I </td> </tr> <tr> <td style="text-align:left;color: gray !important;background-color: yellow !important;"> February 09 </td> <td style="text-align:left;color: gray !important;background-color: yellow !important;"> 03:30pm-05:00pm </td> <td style="text-align:left;font-weight: bold;background-color: yellow !important;"> Advanced Maps II </td> </tr> </tbody> </table> --- layout: false class: center background-image: url(data:image/png;base64,#./assets/img/the_end.png) background-size: cover .left-column[ </br> <img src="data:image/png;base64,#./img/stefan.png" width="90%" style="display: block; margin: auto;" /> ] .right-column[ .left[.small[<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" style="height:1em;fill:currentColor;position:relative;display:inline-block;top:.1em;"> [ comment ] <path d="M464 64H48C21.49 64 0 85.49 0 112v288c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V112c0-26.51-21.49-48-48-48zm0 48v40.805c-22.422 18.259-58.168 46.651-134.587 106.49-16.841 13.247-50.201 45.072-73.413 44.701-23.208.375-56.579-31.459-73.413-44.701C106.18 199.465 70.425 171.067 48 152.805V112h416zM48 400V214.398c22.914 18.251 55.409 43.862 104.938 82.646 21.857 17.205 60.134 55.186 103.062 54.955 42.717.231 80.509-37.199 103.053-54.947 49.528-38.783 82.032-64.401 104.947-82.653V400H48z"></path></svg> [`stefan.juenger@gesis.org`](mailto:stefan.juenger@gesis.org)] </br> .small[<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" style="height:1em;fill:currentColor;position:relative;display:inline-block;top:.1em;"> [ comment ] <path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"></path></svg> [`@StefanJuenger`](https://twitter.com/StefanJuenger)] </br> .small[<svg viewBox="0 0 496 512" xmlns="http://www.w3.org/2000/svg" style="height:1em;fill:currentColor;position:relative;display:inline-block;top:.1em;"> [ comment ] <path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"></path></svg> [`StefanJuenger`](https://github.com/StefanJuenger)] </br> .small[<svg viewBox="0 0 576 512" xmlns="http://www.w3.org/2000/svg" style="height:1em;fill:currentColor;position:relative;display:inline-block;top:.1em;"> [ comment ] <path d="M280.37 148.26L96 300.11V464a16 16 0 0 0 16 16l112.06-.29a16 16 0 0 0 15.92-16V368a16 16 0 0 1 16-16h64a16 16 0 0 1 16 16v95.64a16 16 0 0 0 16 16.05L464 480a16 16 0 0 0 16-16V300L295.67 148.26a12.19 12.19 0 0 0-15.3 0zM571.6 251.47L488 182.56V44.05a12 12 0 0 0-12-12h-56a12 12 0 0 0-12 12v72.61L318.47 43a48 48 0 0 0-61 0L4.34 251.47a12 12 0 0 0-1.6 16.9l25.5 31A12 12 0 0 0 45.15 301l235.22-193.74a12.19 12.19 0 0 1 15.3 0L530.9 301a12 12 0 0 0 16.9-1.6l25.5-31a12 12 0 0 0-1.7-16.93z"></path></svg> [`https://stefanjuenger.github.io`](https://stefanjuenger.github.io)]] </br> ] --- class: middle ## Add-on Slides: Conversion and possible applications --- ## Raster to Points ```r raster_points <- raster::rasterToPoints(immigrant_rate, spatial = TRUE) %>% sf::st_as_sf() raster_points ``` ``` ## Simple feature collection with 13867 features and 1 field ## geometry type: POINT ## dimension: XY ## bbox: xmin: 4094900 ymin: 3084100 xmax: 4121200 ymax: 3112900 ## CRS: +proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000 +ellps=GRS80 +units=m +no_defs ## First 10 features: ## layer geometry ## 1 6.508876 POINT (4103200 3112900) ## 2 45.026178 POINT (4103300 3112900) ## 3 33.185841 POINT (4103400 3112900) ## 4 34.351145 POINT (4103500 3112900) ## 5 25.000000 POINT (4103600 3112900) ## 6 31.147541 POINT (4103700 3112900) ## 7 20.304569 POINT (4103800 3112900) ## 8 12.315271 POINT (4103900 3112900) ## 9 7.894737 POINT (4104100 3112900) ## 10 7.407407 POINT (4104200 3112900) ``` --- ## Points to Raster ```r points_raster <- raster_points %>% sf::st_coordinates() %>% dplyr::bind_cols(Z = raster_points$layer) %>% raster::rasterFromXYZ(crs = 3035) points_raster ``` ``` ## class : RasterLayer ## dimensions : 289, 264, 76296 (nrow, ncol, ncell) ## resolution : 100, 100 (x, y) ## extent : 4094850, 4121250, 3084050, 3112950 (xmin, xmax, ymin, ymax) ## crs : +proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000 +ellps=GRS80 +units=m +no_defs ## source : memory ## names : Z ## values : 0.6637168, 100 (min, max) ``` --- ## Application: Point Pattern Analysis Using Global Kernel Densities (‘Heatmap’) .pull-left[ ```r kernel_densities <- raster_points %>% dplyr::filter(layer > 25) %>% sf::as_Spatial() %>% as("ppp") %>% spatstat::density.ppp(sigma = 250) %>% as.data.frame() %>% raster::rasterFromXYZ(crs = 3035) ``` ] .pull-right[ <img src="data:image/png;base64,#1_4_Raster_Data_files/figure-html/plot-densities-1.png" style="display: block; margin: auto;" /> ] --- ## Raster to Polygons .pull-left[ ```r polygon_raster <- immigrant_rate %>% raster::rasterToPolygons() %>% sf::st_as_sf() ``` ] .pull-right[ <img src="data:image/png;base64,#1_4_Raster_Data_files/figure-html/plot-polygon-raster-1.png" style="display: block; margin: auto;" /> ] --- ## Application: Rotation in Space (Tomorrow’s Session) <img src="data:image/png;base64,#1_4_Raster_Data_files/figure-html/plot-polygon-raster-rotated-1.png" style="display: block; margin: auto;" /> --- ## Rasterize Using the `stars` Package In the `raster` (or `terra`) package are functions to convert vector data into raster data, a process called rasterizing. I find these function a bit tricky as they require defining a 'background' raster layer on which the vector data are projected. Thus, I prefer the following method using the `stars` package: ```r raster_polygon <- polygon_raster %>% stars::st_rasterize(dx = 100, dy = 100) %>% as("Raster") ``` --- ## `raster`'s Successor: The `terra` Package `R` and its packages are in continuous development. - functions change - new packages appear - old packages get deprecated -- The developers of the `raster` package decided to rewrite the functions so that it's [simpler, better, and faster](https://rspatial.org/terra/pkg/index.html) **Thus, `terra` will be the `raster` package's successor in the future.**