zonal
is an active package for intersecting vector aggregation units with large gridded data. While there are many libraries that seek to tackle this problem (see credits) we needed a library that could handle large gridded extents with multiple time layers with both many small vector units and few large units.
We also seek to segment the creation of grid weights from the zonal execution so that the same weight map can be applied across different products with the same structure (e.g. MODIS ET and MODIS LAI)
You can install the development version of zonal
from GitHub with:
# install.packages("remotes")
remotes::install_github("mikejohnson51/zonal")
This is a basic example that takes a NetCDF file containing a 4km grid for the continental USA and daily precipitation for the year 1979 (365 layers). Our goal is to subset this file to the southern USA, and compute daily county level averages. The result is a daily rainfall average for each county.
library(zonal)
library(sf)
library(dplyr)
library(ggplot2)
file <- '/Users/mjohnson/Downloads/pr_1979.nc'
AOI <- AOI::aoi_get(state = "south", county = "all")
system.time({
# Build Weight Grid
w = weighting_grid(file, AOI, "geoid")
# Intersect
pr_zone = execute_zonal(file, w)
})
#> user system elapsed
#> 11.830 2.085 9.710
# PET zone: Counties, time slices/ID
dim(pr_zone)
#> [1] 1421 366
# Plot Day with the maximum single county max rainfall.
n = colnames(pr_zone)[which(pr_zone[,-1] == max(pr_zone[,-1]), arr.ind = TRUE)[2] + 1]
plot(merge(AOI, pr_zone)[n], border = NA)
# Plot Day with the maximum county wide rainfall
n2 = names(which.max(colSums(select(pr_zone, -geoid))))
plot(merge(AOI, pr_zone)[n2], border = NA)
data = pr_zone %>%
slice_max(rowSums(select(., -geoid))) %>%
tidyr::pivot_longer(-geoid, names_to = "date", values_to = "prcp")
head(data)
#> # A tibble: 6 x 3
#> geoid date prcp
#> <chr> <chr> <dbl>
#> 1 37175 1979-01-01 48.3
#> 2 37175 1979-01-02 19.1
#> 3 37175 1979-01-03 0
#> 4 37175 1979-01-04 0
#> 5 37175 1979-01-05 1.96
#> 6 37175 1979-01-06 12.9
One of the largest limitations of existing utilites is the ability to handle categorical data. Here we show an example for a 1km grid storing land cover data from MODIS. This grid was creating by mosacing 19 MODIS tiles covering CONUS.
file = '/Users/mjohnson/Downloads/MCD12Q1.006.nc'
rcl = read.csv("inst/modis_lc.csv") %>%
select(from = Class, to = short)
system.time({
# Build Weight Grid
w = weighting_grid(file, AOI, "geoid")
# Intersect, and relclassify
lc = execute_zonal_cat(file, w, rcl)
})
#> user system elapsed
#> 7.115 0.843 4.889