Search code examples
rmapspolygonrasterr-sf

Aggregate values in raster using SF


Aggregate values in raster using SF

What I need is to aggregate values of some metric for each raster. Let's suppose we have some data - coordinates and value and I want to create a heatmap.

Firstly, I create a grid and raster using the simple feature framework. Now I need to take every coordinate in df and check if they are in one raster. Then for each raster calculate the mean of any other aggregation function.


# Packages ----------------------------------------------------------------


library(raster)
library(tidyverse)
library(sf)
library(sp)


# Border Data and Grid ----------------------------------------------------

Regions <- getData("GADM", country= "CZE", level = 1)
Regions %>% 


Regions <-
  Regions %>% st_as_sf()

grid_spacing <- 0.25

polygony <- st_make_grid(Regions, square = T,
                         cellsize = c(grid_spacing, grid_spacing)) %>%
  st_sf()

plot(polygony, col = 'white')
plot(st_geometry(CZ), add = T)

A = st_intersection(polygony, CZ)


# Artifial Values to be use -----------------------------------------------
df <- 
  tibble(long = runif(500, 13.27857, 14),
         lat = runif(500, 49, 50),
         price = rnbinom(500, size = 40, 0.3))

df %>% 
  ggplot(aes(long, lat, color = values)) + 
  geom_point()

A <- 
  A %>% 
  # Here Val shall be calculated as a mean of observations within each rastel grid cell
  mutate(val = rnorm(n = 202))

# Since not every raster cell has observations inside some NAN will be present
A[5, 'val']  = NaN
A[25, 'val']  = NaN

A %>% 
  ggplot(aes(fill = val)) + 
  geom_sf()



# What I need -------------------------------------------------------------

# For each raster in A calculate the mean of price for coordinates within this raster grid.


I essentially need some equivalent of https://www.rdocumentation.org/packages/raster/versions/3.4-5/topics/rasterize within the sf framework.

However, I want to plot to look as in the example I really need the raster to have a shape of a given grid.


Solution

  • To aggregate point values across a grid and stay with sf, you can do the following:

    library(dplyr)
    library(sf)
    
    # get data. using your example, we'll take spatial data from the raster package
    Regions <- raster::getData("GADM", country= "CZE", level = 1)
    
    # convert spdf to sf
    Regions <- Regions %>% st_as_sf()
    
    # create a grid sf object
    grid_spacing <- 0.25
    
    polygony <- st_make_grid(Regions, square = T,
                             cellsize = c(grid_spacing, grid_spacing)) %>%
      st_sf() %>% 
      mutate(ID = row_number()) # add a unique ID to each grid cell
    
    # clip grid to shape of country polygons
    A <- st_intersect(polygony, Regions)
    
    # create fake data with coordinates and prices
    df <- tibble(long = runif(500, 13.27857, 14),
             lat = runif(500, 49, 50),
             price = rnbinom(500, size = 40, 0.3))
    
    # convert the df to sf point layer
    points <- st_as_sf(df, coords = c("long", "lat"), crs = st_crs(A))
    
    # spatially join grid to points, so that each point is assigned the grid ID into which it falls
    pointsID <- st_join(points, A)
    
    # group and summarize point values by grid ID
    pointsID <- pointsID %>% 
      as.data.frame() %>% 
      group_by(ID) %>% 
      summarize(avg_price = mean(price))
    
    # join aggregated values back to your grid
    A<- left_join(A, pointsID, by = "ID")
    
    plot(A["avg_price"])
    

    grid with values