Chapter 8 Raster Operations
Downloading Cal-Adapt climate data as rasters makes sense if your analysis involves methods that require the entire surface, and/or uses raster methods such as delineating isopleths, classification, or stacking on other raster layers. You may also want to use rasters simply for convenience, for example if you have a lot of sample points and/or will be extracting values many times. Downloading rasters only has to be done once, after which you can query them locally.
In this chapter, we’ll see how to download rasters to compute the number of frost days across Fresno county, which is a large county that includes both valley and mountainous areas. Our first output will be a raster that shows the number of frost days per year for 30 years of observed minimum daily temperature.
8.1 Load Packages
As usual, we start by loading a bunch of packages into memory and specifying our preferences for conflicting function names:
library(caladaptr)
library(units)
library(ggplot2)
library(dplyr)
library(tidyr)
library(lubridate)
library(sf)
library(stars)
Set conflicted preferences:
library(conflicted)
conflict_prefer("filter", "dplyr", quiet = TRUE)
conflict_prefer("count", "dplyr", quiet = TRUE)
conflict_prefer("select", "dplyr", quiet = TRUE)
8.2 Fetch TIFs
We’ll start by computing the number of frost days from observed historic temperature data from the Livneh dataset.
<- ca_loc_aoipreset(type = "counties", idfld = "fips", idval = "06019") %>%
fres_cap ca_livneh(TRUE) %>%
ca_cvar("tasmin") %>%
ca_period("day") %>%
ca_years(start = 1981, end = 2010)
%>% ca_preflight(check_for = "getrst") fres_cap
## General issues
## - none found
## Issues for downloading rasters
## - none found
plot(fres_cap, locagrid = TRUE)
To download TIF files, we need to specify an output directory. Below we’ll put them in a directory under R’s home directory (i.e., My Documents):
<- file.path("~", "ca_data/fresno")) (tiffs_dir
## [1] "~/ca_data/fresno"
if (!file.exists(tiffs_dir)) dir.create(tiffs_dir, recursive = TRUE)
Now we can download the tif(s) using ca_getrst_stars()
:
<- fres_cap %>%
fres_fn ca_getrst_stars(out_dir = tiffs_dir, mask = TRUE, quiet = FALSE,
normalize_path = TRUE, overwrite = FALSE)
## - ~/ca_data/fresno/tasmin_day_livneh_fips-06019.tif found. Skipping.
## - Done. Read TIFs in with `ca_stars_read`
list.files(tiffs_dir)
## [1] "tasmin_day_livneh_fips-06019.attr.rds"
## [2] "tasmin_day_livneh_fips-06019.tif"
8.3 Import TIFs in R
At this point we have TIF files, but they are not loaded into R. The recommended way to import them is as stars objects using:
<- fres_fn %>% ca_stars_read() fres_star_lst
ca_stars_read()
returns a list. Let’s see what’s in it:
class(fres_star_lst)
## [1] "list"
length(fres_star_lst)
## [1] 1
class(fres_star_lst[[1]])
## [1] "stars"
1]] fres_star_lst[[
## stars object with 3 dimensions and 1 attribute
## attribute(s), summary of first 1e+05 cells:
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## tasmin_day_livneh_fips-06019 -22.16 -4.13 2.95 0.7203694 6.13 13.61
## NA's
## tasmin_day_livneh_fips-06019 65915
## dimension(s):
## from to offset delta refsys point values x/y
## x 1 42 -120.938 0.0625 WGS 84 FALSE NULL [x]
## y 1 28 37.625 -0.0625 WGS 84 FALSE NULL [y]
## date 1 10957 1981-01-01 1 days Date NA NULL
In summary, our stars object has 42 columns and 28 rows, and 10,957 bands or layers, which is one layer for each day (365 * 30 = 10,950).
Next, we have compute the number of frost days per year. Normally, we would try to split the ‘date’ dimension into two (year and Julian date), but that won’t work because years have different number of days. Instead we’ll loop through the years, generate a stars object with the number of freeze days, and then combine them all back together.
Step 1 is to generate the years:
## Get the years from the values of the "date" dimension
<- fres_star_lst[[1]] %>%
years_int st_get_dimension_values("date") %>%
as.Date() %>%
year() %>%
unique() %>%
sort()
years_int
## [1] 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995
## [16] 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010
Next, create an empty list to hold stars objects:
<- list() numfrzday_lst
Next, loop through the years and add a stars object to the list:
for (i in 1:length(years_int)) {
<- years_int[i]
yr as.character(yr)]] <- (fres_star_lst[[1]] %>%
numfrzday_lst[[filter(year(date) == yr) < 0) %>%
setNames("freeze_yn") %>%
st_apply(c("x", "y"), sum) %>%
setNames("num_fd")
}
names(numfrzday_lst)
## [1] "1981" "1982" "1983" "1984" "1985" "1986" "1987" "1988" "1989" "1990"
## [11] "1991" "1992" "1993" "1994" "1995" "1996" "1997" "1998" "1999" "2000"
## [21] "2001" "2002" "2003" "2004" "2005" "2006" "2007" "2008" "2009" "2010"
Combine the elements of numfrzday_lst
into a single stars object:
<- do.call(c, c(numfrzday_lst,
fres_numfd_year list(along = list(year = years_int))))
fres_numfd_year
## stars object with 3 dimensions and 1 attribute
## attribute(s):
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## num_fd 0 12 30 88.15885 173 351 23250
## dimension(s):
## from to offset delta refsys point values x/y
## x 1 42 -120.938 0.0625 WGS 84 FALSE NULL [x]
## y 1 28 37.625 -0.0625 WGS 84 FALSE NULL [y]
## year 1 30 1981 1 NA NA NULL
Now we can plot:
plot(fres_numfd_year, axes = TRUE)
More coming soon…