3.3 Detrending
Now let’s move on to detrending. We’ll use the HadCRUT5 global mean surface temperature dataset.
gmst <- read_csv("https://github.com/LinkedEarth/Pyleoclim_util/raw/master/pyleoclim/data/HadCRUT.5.0.1.0.analysis.summary_series.global.annual.csv") %>%
select(time = Time,temp = `Anomaly (deg C)`)
ggplot(gmst, aes(x = time, y = temp)) +
geom_line() +
labs(x = 'Time [year C.E.]', y = 'GMST [°C]') +
theme_light()
3.3.1 Detrending methods in R
Let’s apply 3 methods: linear detrending, Empirical Mode Decomposition (EMD), and Savitzky-Golay filter:
# Linear detrending
gmstLinear <- gmst
gmstLinear$detrended <- pracma::detrend(gmstLinear$temp)
gmstLinear$trend <- gmstLinear$temp - gmstLinear$detrended
gmstLinear$method <- "Linear"
# EMD using the EMD package
library(EMD)
emd_result <- emd(gmst$temp, boundary='symmetric', max.imf=4)
gmstEmd <- gmst
gmstEmd$detrended <- gmst$temp-emd_result$residue
gmstEmd$trend <- gmstEmd$temp - gmstEmd$detrended
gmstEmd$method <- "EMD"
# Savitzky-Golay filter
gmstSg <- gmst
gmstSg$trend <- signal::sgolayfilt(gmst$temp, p = 3, n = 51)
gmstSg$detrended <- gmst$temp - gmstSg$trend
gmstSg$method <- "Savitzky-Golay"
#prepare the data for plotting
gmstToPlot <- dplyr::bind_rows(gmstLinear,gmstEmd,gmstSg) %>%
tidyr::pivot_longer(cols = -c(time,method),values_to = "Temperature",names_to = "options") %>%
mutate(method = factor(method,levels = c("Linear","EMD","Savitzky-Golay")))
# Plot it!
ggplot(gmstToPlot) +
geom_line(aes(x = time, y = Temperature, color = options)) +
facet_grid(method ~ .) +
theme_light()
The linear trend here does a decent job at capturing first-order behavior. The EMD (approximated by SSA) and Savitzky-Golay methods also capture the nonlinear trend.
3.3.2 SSA detrending
Another option to isolate a non-linear trend is Singular Spectrum Analysis (SSA). If there is a prominent trend, it is often the first mode coming out of that analysis.

The first mode accounts for most fraction of the variance. Let’s compute this:
## [1] "55%"
Let’s use this mode as the trend:
ssa_trend <- reconstruct(gmst_ssa, groups = list(trend = 1))
gmst_ssa_dtd <- data.frame(time = gmst$time, temp = gmst$temp - ssa_trend$trend)
ggplot(gmst, aes(x = time, y = temp)) +
geom_line() +
geom_line(aes(y = ssa_trend$trend, color = "SSA trend"), alpha = 0.8) +
geom_line(aes(y = gmst_ssa_dtd$temp, color = "SSA detrended"), alpha = 0.8) +
labs(x = 'Time [year C.E.]', y = 'GMST [°C]', color = '') +
theme_light()