Section 3 Temperature-elevation associations
In this script, we calculate temperatures across elevational bands in the Eastern and Western Himalayas.
3.1 Load necessary libraries
Code
library(raster)
library(stringi)
library(glue)
library(gdalUtils)
library(purrr)
library(dplyr)
library(tidyr)
library(scales)
library(ggplot2)
library(ggthemes)
library(sf)
library(mapview)
library(rgeos)
# get ci func
ci <- function(x){qnorm(0.975)*sd(x, na.rm = T)/sqrt(length(x))}
# prep mode function to aggregate
funcMode <- function(x, na.rm = T) {
ux <- unique(x)
ux[which.max(tabulate(match(x, ux)))]
}
# a basic test
assertthat::assert_that(funcMode(c(2,2,2,2,3,3,3,4)) == as.character(2),
msg = "problem in the mode function") # works
3.2 Load shapefiles
Code
# Load shapefiles
# Please note the below shapefile consists of multiple polygons that combines the east and west
himalayas <- st_read("data/shapefiles/shapefile_himalaya.shp")
mapview(himalayas)
# Need to merge a few polygons to essentially split himalayas into the west and the east
# This will have to be done at 83E for Nepal
# Merge polygons for western himalayas
west_toMerge <- himalayas[c(3,4,7,8,9,10),]
westHim <- st_crop(west_toMerge,xmin=68.03321,ymin=23.69771,xmax=83,ymax=37.07761)
# Merge polygons for eastern himalayas
east_toMerge <- himalayas[c(1,2,5,6,10),]
east_toMerge <- st_buffer(east_toMerge, dist=0)
eastHim <- st_crop(east_toMerge,xmin=83,ymin=25.96462,xmax=97.4115,ymax=30.44728)
3.3 Prepare elevation rasters
Code
# load elevation and crop to hills size, then mask by hills
# Please note that this file is large and is not uploaded to GitHub and can be downloaded from SRTM (Farr et al. 2007)
alt <- raster("data/elevation/alt")
alt.east <- crop(alt, as(eastHim, "Spatial"))
alt.west <- crop(alt, as(westHim, "Spatial"))
rm(alt); gc()
# get slope and aspect
slopeEast <- terrain(x = alt.east, opt = c("slope", "aspect"))
slopeWest <- terrain(x = alt.west, opt = c("slope", "aspect"))
# stack rasters
elevEast <- raster::stack(alt.east, slopeEast)
elevWest <- raster::stack(alt.west, slopeWest)
rm(alt.east,alt.west); gc()
3.4 Prepare climate rasters
Code
# list chelsa files
# CHELSA files are not uploaded to GitHub as they are extremely large and can be downloaded from https://chelsa-climate.org/
# Please note that we downloaded four rasters corresponding to minimum and maximum temperatures for the months of January and June
chelsaFiles <- list.files("data/chelsa/",
full.names = TRUE,
pattern = "*.tif")
# gather chelsa data over the east
chelsaEast <- purrr::map(chelsaFiles, function(chr){
a <- raster(chr)
crs(a) <- crs(elevEast)
a <- crop(a, as(eastHim, "Spatial"))
return(a)
})
# gather chelsa data over the west
chelsaWest <- purrr::map(chelsaFiles, function(chr){
a <- raster(chr)
crs(a) <- crs(elevWest)
a <- crop(a, as(westHim, "Spatial"))
return(a)
})
# Divide temperature values by 10 for east
chelsaEast[[1]] <- chelsaEast[[1]]/10
chelsaEast[[2]] <- chelsaEast[[2]]/10
chelsaEast[[3]] <- chelsaEast[[3]]/10
chelsaEast[[4]] <- chelsaEast[[4]]/10
# Divide temperature values by 10 for the west
chelsaWest[[1]] <- chelsaWest[[1]]/10
chelsaWest[[2]] <- chelsaWest[[2]]/10
chelsaWest[[3]] <- chelsaWest[[3]]/10
chelsaWest[[4]] <- chelsaWest[[4]]/10
# stack chelsa data for the east and west
chelsaEast <- raster::stack(chelsaEast)
chelsaWest <- raster::stack(chelsaWest)
### Stack prepared rasters
# stack rasters for efficient reprojection later
env_east <- stack(elevEast, chelsaEast)
env_west <- stack(elevWest, chelsaWest)
# get proper names
elev_names <- c("elev", "slope", "aspect")
chelsa_names <- c("maxTemp_Jan", "maxTemp_June","minTemp_Jan","minTemp_June")
names(env_east) <- as.character(glue('{c(elev_names, chelsa_names)}'))
names(env_west) <- as.character(glue('{c(elev_names, chelsa_names)}'))
3.5 Extracting data across elevational bands
Code
# make duplicate stack
envEast <- env_east[[c("elev", chelsa_names)]]
envWest <- env_West[[c("elev", chelsa_names)]]
# convert to list
envEast <- as.list(envEast)
envWest <- as.list(envWest)
# map get values over the stack
envEast <- purrr::map(envEast, getValues)
envWest <- purrr::map(envWest, getValues)
names(envEast) <- c("elev", chelsa_names)
names(envWest) <- c("elev", chelsa_names)
# convert to dataframe and round to a particular elevational band you need
envEast <- bind_cols(envEast)
envWest <- bind_cols(envWest)
envEast <- drop_na(envEast) %>%
mutate(elev_round = plyr::round_any(elev, 100)) %>% # changed to 100 m intervals
dplyr::select(-elev) %>%
group_by(elev_round) %>%
summarise_all(.funs = list(~mean(.), ~ci(.))) %>%
mutate(tempRange_Jan = (maxTemp_Jan_mean - minTemp_Jan_mean),
tempRange_June = (maxTemp_June_mean - minTemp_June_mean))
envWest <- drop_na(envWest) %>%
mutate(elev_round = plyr::round_any(elev, 100)) %>% # changed to 100 m intervals
dplyr::select(-elev) %>%
group_by(elev_round) %>%
summarise_all(.funs = list(~mean(.), ~ci(.))) %>%
mutate(tempRange_Jan = (maxTemp_Jan_mean - minTemp_Jan_mean),
tempRange_June = (maxTemp_June_mean - minTemp_June_mean))
# Write results to a .csv
west_data <- write.csv(env,"results/westHim_100.csv", row.names = F)
east_data <- write.csv(env,"results/eastHim_100.csv", row.names = F)
3.6 Plot temperature as a function of elevation
Code
# eastern Himalayas
fig_climate_elevEast <- ggplot(envEast)+
geom_line(aes(x = elev_round, y = mean),
size = 0.2, col = "grey")+
geom_pointrange(aes(x = elev_round, y = mean, ymin=mean-ci, ymax=mean+ci),
size = 0.3)+
scale_x_continuous(labels = scales::comma)+
scale_y_continuous(labels = scales::comma)+
facet_wrap(~clim_var, scales = "free_y")+
theme_few()+
labs(x = "elevation (m) at 100m intervals", y = "CHELSA variable value")+
theme(axis.title = element_text(size = 16, face = "bold"),
axis.ticks.length.x = unit(.5, "cm"),
axis.text = element_text(size = 14),
legend.title = element_blank(),
legend.key.size = unit(1,"cm"),
legend.text = element_text(size = 12))
# save ggplots accordingly
ggsave(fig_climate_elevEast, filename = "figs/fig_eastHim_elev100.png",
height = 10, width = 14, device = png(), dpi = 300, units="in"); dev.off()
# western Himalayas
fig_climate_elevWest <- ggplot(envWest)+
geom_line(aes(x = elev_round, y = mean),
size = 0.2, col = "grey")+
geom_pointrange(aes(x = elev_round, y = mean, ymin=mean-ci, ymax=mean+ci),
size = 0.3)+
scale_x_continuous(labels = scales::comma)+
scale_y_continuous(labels = scales::comma)+
facet_wrap(~clim_var, scales = "free_y")+
theme_few()+
labs(x = "elevation (m) at 100m intervals", y = "CHELSA variable value")+
theme(axis.title = element_text(size = 16, face = "bold"),
axis.ticks.length.x = unit(.5, "cm"),
axis.text = element_text(size = 14),
legend.title = element_blank(),
legend.key.size = unit(1,"cm"),
legend.text = element_text(size = 12))
# save ggplots accordingly
ggsave(fig_climate_elevWest, filename = "figs/fig_westHim_elev100.png",
height = 10, width = 14, device = png(), dpi = 300, units="in"); dev.off()