::p_load(data.table, tidyverse, splints, survey, lfe, scales) pacman
Many climate-society papers project the impacts of predicted climate change on the outcome of interest (guilty!). This post include code to conduct this kind of “climate projection exercise”. The idea is to combine a dose-response function
However, we’ll be estimating this integral numerically, because
Simulate a mostly-but-not-entirely increasing sinusoidal dose-response function, where
set.seed(42)
<- 1000
N <- data.table(T = runif(N, 0, 40))
dt := -10 + 0.5 * T + 8 * sin(T / 6) + rnorm(N)]
dt[, y
ggplot(data = dt, aes(x = T, y = y)) + geom_point() + theme_minimal()
Estimate damage function
Since we normally wouldn’t know the exact functional form of the DGP, we’ll estimate
<- quantile(dt$T, probs = c(0.25, 0.5, 0.75))
knots <- range(dt$T); degree = 3; intercept = TRUE
boundary <- ns(dt$T, knots = knots, Boundary.knots = boundary, intercept=intercept)
X
# Estimate with both felm and lm to demonstrate
<- felm(y ~ X - 1, data = dt)
fit <- lm(y ~ X - 1, data = dt) lmfit
Generate climate predictions
Generate some climate predictions. Normally you’d do this by combining the output from a climate model - see Auffhammer et al (2014) for details on how to do this - but today we’ll just take the realized “weather” from above and increase it by 5 on average. Construct a sequence of equally spaced intervals that includes the range of observed and predicted temperature and create basis vectors for both. Then estimate the PDFs of the current and future distributions and take the difference between them as
:= T + rnorm(N, 5, 5)]
dt[, T_future
<- 1 # Set interval for prediction: lower values = more precision (diminishing returns here)
width <- seq(min(dt[, list(T, T_future)]), max(dt[, list(T, T_future)]), width)
s
# Could use a histogram instead of a PDF here
<- data.table(s = s,
densities cur_density = approxfun(density(dt$T))(s),
fut_density = approxfun(density(dt$T_future))(s))
is.na(cur_density), cur_density := 0]
densities[is.na(fut_density), fut_density := 0]
densities[:= fut_density - cur_density]
densities[, diff_density
ggplot(data = melt(densities, id.vars = "s"), aes(x = s, y = value, colour = variable, group = variable)) +
geom_line() + theme_minimal()
Predict along interval
<- ns(s, knots = knots, Boundary.knots = boundary, intercept=intercept)
Xp colnames(Xp) <- paste0("X", colnames(Xp))
Predict from felm output with svycontrast
Predict over the sequence using survey::svycontrast
. This works with both lm
and felm
.
<- list()
res.list for (i in 1:nrow(Xp)) {
<- s[i]
this.x <- c(unlist(Xp[i, ])) # Sometimes, will need to fill in values for other covariates (0s or means?), e.g. ppt
this.row <- as.data.table(svycontrast(fit, this.row))
temp.dt :=this.x]
temp.dt[, xsetnames(temp.dt, c("coef", "se", "x"))
as.character(this.x)]] <- temp.dt
res.list[[
}<- rbindlist(res.list)
result_survey
ggplot(data = result_survey, aes(x = x, y = coef)) +
geom_point(data = dt, mapping = aes(x = T, y = y), colour = "blue", alpha = 0.5) +
geom_line() +
theme_minimal()
Predict from lm output with predict
Alternative to usingy survey::svycontrast
loop is to do the same using predict.lm
, but there is no equivalent predict.felm
.
# Note the list notation here. Need to tell predict that Xp is replacing X o
<- as.data.table(predict(lmfit, newdata = list(X = Xp), se.fit = T))
result_predict := s]
result_predict[, s ggplot(data = result_predict, aes(x = s, y = fit)) +
geom_point(data = dt, mapping = aes(x = T, y = y), colour = "blue", alpha = 0.5) +
geom_line() +
theme_minimal()
Compute damages
Finally, compute damages:
<- result_survey$coef
f <- densities$diff_density
g
sum(f * g * width)
[1] 3.370896
Note that the interpretation of this sum is that it is the amount of damage at the given observational unit for this amount of climate change. So if this is a regression of, say, daily crimes in a county on temperature, then the implication is the given amount of climate change will result in this many more crimes per county per day on average. Of course, this relies on the usual assumptions about the extrapolation of the results from weather regressions to climate effects.
Substitute in different damage functions