从 GAM 预测 R 中分组数据帧的值
predict values from GAM for grouped dataframe in R
我有一个不同年份不同纬度的年平均温度值的数据集。我想用它来预测给定年份可以找到给定温度的纬度;即 "in 1980, at what latitude would the mean annual temperature have been 20C?"
为此我需要使用特定年份的模型,因为纬度和温度之间的关系会随着时间发生变化(尽管在下面的示例数据中没有,它是随机生成的)。这将涉及:
- 按年份将 GAM 拟合到数据集 grouped/split。
- 对于每个不同的 GAM(即每年),使用
predict.gam
计算温度列表中每个元素的预测值。
- 重新组合这些以获得一个数据框,其中列代表
year
、newdata_value
(用于预测的温度值)和 predicted_value
(将每个 newdata_value
馈入特定年份 GAM 的纬度)。
这是一个玩具数据集:
years <- seq(1968, 2018, 1)
lat <- seq(34.5, 44.5, 1)
dat <- expand.grid(years, lat)
names(dat) <- c("years","lat")
dat$temp <- runif(dim(dat)[1], 5, 20) # add random temperature data points
newdata_values <- seq(2, 16, 2) # temperature values to use for prediction
我尝试了各种 purrr
和 split-apply-combine
解决方案,但没有找到任何解决方案。有什么建议么?
一种方法是使用嵌套数据框。我使用了在 this tutorial.
中找到的代码
您可以按年份分组并使用 nest
。我还将重命名列并添加新值以进行预测:
library(tidyverse); library(mgcv)
names(dat) <- c('year', 'lat', 'temp')
dat2 <- dat %>% group_by(year) %>% nest()
dat2 <- dat2 %>% mutate(newdata_value = rep(list(newdata_values), n_distinct(year)))
然后您定义一些辅助函数以使 tidyverse 代码更清晰(我假设您使用 mgcv
包中的 gam)。然后将模型函数映射到数据并将预测函数映射到拟合模型:
lat_gam <- function(df) {
gam(lat ~ s(temp), data = df)
}
pred_gam <- function(mod) {
predict.gam(mod, newdata = data.frame(temp = newdata_values))
}
dat2 <- dat2 %>% mutate(model = map(data, lat_gam))
dat2 <- dat2 %>% mutate(predicted_value = map(model, pred_gam))
dat2 %>% select(-data, -model) %>% unnest(cols = c(newdata_value, predicted_value))
最后一行完全是可选的,只是按照您在 3) 中指定的方式打印最终输出
这是一个 data.table 方法:
library(data.table)
library(mgcv)
setDT(dat)
dat[, .(pred = c(predict.gam(gam(lat ~ temp), list(temp = newdata_values))),
newdata_values),
by = years]
我遇到的唯一问题是 predict.gam(...)
调用 returns 一个数组。 c(predict.gam(...))
将其转换为数组。
没有完美格式的类似基本方法:
by(dat[, -1],
dat[, 1],
function(DF) {
mod = gam(lat ~ temp, data = DF)
pred = predict.gam(mod, list(temp = newdata_values))
data.frame(newdata_values, pred)
}
)
另一种选择是拟合允许 lat/temp 关系随年份变化的模型。有几种选择。下面拟合一个模型,其中每一年都有一个独立的关系:
gam(lat ~ year + s(temp, by = year), data = dat)
请注意,对于此公式,year
应编码为一个因子。
另一种方法是允许 lat/temp 关系按年 平滑地变化 ,如果这种关系随时间逐渐变化,这是一个合理的模型。在这种情况下,您需要使用 张量积平滑 (te()
) 来指示不同尺度(度、年)的变量之间的双向交互作用:
gam(lat ~ te(temp, year), data = dat)
在这两种情况下,您都可以使用 predict.gam(model, newdata = new_dat)
进行预测,其中 new_dat
具有 year
和 temp
列。
我有一个不同年份不同纬度的年平均温度值的数据集。我想用它来预测给定年份可以找到给定温度的纬度;即 "in 1980, at what latitude would the mean annual temperature have been 20C?"
为此我需要使用特定年份的模型,因为纬度和温度之间的关系会随着时间发生变化(尽管在下面的示例数据中没有,它是随机生成的)。这将涉及:
- 按年份将 GAM 拟合到数据集 grouped/split。
- 对于每个不同的 GAM(即每年),使用
predict.gam
计算温度列表中每个元素的预测值。 - 重新组合这些以获得一个数据框,其中列代表
year
、newdata_value
(用于预测的温度值)和predicted_value
(将每个newdata_value
馈入特定年份 GAM 的纬度)。
这是一个玩具数据集:
years <- seq(1968, 2018, 1)
lat <- seq(34.5, 44.5, 1)
dat <- expand.grid(years, lat)
names(dat) <- c("years","lat")
dat$temp <- runif(dim(dat)[1], 5, 20) # add random temperature data points
newdata_values <- seq(2, 16, 2) # temperature values to use for prediction
我尝试了各种 purrr
和 split-apply-combine
解决方案,但没有找到任何解决方案。有什么建议么?
一种方法是使用嵌套数据框。我使用了在 this tutorial.
中找到的代码您可以按年份分组并使用 nest
。我还将重命名列并添加新值以进行预测:
library(tidyverse); library(mgcv)
names(dat) <- c('year', 'lat', 'temp')
dat2 <- dat %>% group_by(year) %>% nest()
dat2 <- dat2 %>% mutate(newdata_value = rep(list(newdata_values), n_distinct(year)))
然后您定义一些辅助函数以使 tidyverse 代码更清晰(我假设您使用 mgcv
包中的 gam)。然后将模型函数映射到数据并将预测函数映射到拟合模型:
lat_gam <- function(df) {
gam(lat ~ s(temp), data = df)
}
pred_gam <- function(mod) {
predict.gam(mod, newdata = data.frame(temp = newdata_values))
}
dat2 <- dat2 %>% mutate(model = map(data, lat_gam))
dat2 <- dat2 %>% mutate(predicted_value = map(model, pred_gam))
dat2 %>% select(-data, -model) %>% unnest(cols = c(newdata_value, predicted_value))
最后一行完全是可选的,只是按照您在 3) 中指定的方式打印最终输出
这是一个 data.table 方法:
library(data.table)
library(mgcv)
setDT(dat)
dat[, .(pred = c(predict.gam(gam(lat ~ temp), list(temp = newdata_values))),
newdata_values),
by = years]
我遇到的唯一问题是 predict.gam(...)
调用 returns 一个数组。 c(predict.gam(...))
将其转换为数组。
没有完美格式的类似基本方法:
by(dat[, -1],
dat[, 1],
function(DF) {
mod = gam(lat ~ temp, data = DF)
pred = predict.gam(mod, list(temp = newdata_values))
data.frame(newdata_values, pred)
}
)
另一种选择是拟合允许 lat/temp 关系随年份变化的模型。有几种选择。下面拟合一个模型,其中每一年都有一个独立的关系:
gam(lat ~ year + s(temp, by = year), data = dat)
请注意,对于此公式,year
应编码为一个因子。
另一种方法是允许 lat/temp 关系按年 平滑地变化 ,如果这种关系随时间逐渐变化,这是一个合理的模型。在这种情况下,您需要使用 张量积平滑 (te()
) 来指示不同尺度(度、年)的变量之间的双向交互作用:
gam(lat ~ te(temp, year), data = dat)
在这两种情况下,您都可以使用 predict.gam(model, newdata = new_dat)
进行预测,其中 new_dat
具有 year
和 temp
列。