прогнозировать значения из GAM для сгруппированного кадра данных в R - PullRequest
6 голосов
/ 23 октября 2019

У меня есть набор данных среднегодовых значений температуры на разных широтах в разные годы. Я хочу использовать это, чтобы предсказать широту, на которой данная температура может быть найдена в данном году;то есть, «в 1980 году, на какой широте среднегодовая температура была бы 20 ° C?»

Мне нужно использовать для этого модели, относящиеся к году, потому что соотношение между широтой и температурой менялось с течением времени (хотя не в приведенных ниже выборочных данных, которые генерируются случайным образом). Это будет включать:

  1. Подгонка GAM к набору данных, сгруппированных / разделенных по годам.
  2. Для каждого отдельного GAM (то есть для каждого года) используйте predict.gam, чтобы вычислить прогнозируемое значение для каждого элемента в списке температур.
  3. Рекомбинируйте их, чтобы получить кадр данных со столбцами, представляющими 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 и ничего не понял. Какие-либо предложения?

Ответы [ 3 ]

5 голосов
/ 30 октября 2019

Другой вариант заключается в подборе модели, которая позволяет варьировать широтно-временную зависимость в зависимости от года. Есть несколько вариантов для этого. Следующее соответствует модели, в которой каждый год имеет независимую связь:

gam(lat ~ year + s(temp, by = year), data = dat)

Обратите внимание, что для этой формулировки year должно быть закодировано как коэффициент.

Альтернативой может быть разрешениеОтношения широта / температура могут меняться плавно по годам, что является разумной моделью, если эти отношения постепенно изменяются со временем. В этом случае вы захотите использовать тензорное произведение сглаживания (te()), чтобы указать двустороннее взаимодействие между переменными, находящимися в разных масштабах (градусах, годах):

gam(lat ~ te(temp, year), data = dat)

В обоих случаях вы можете затем сделать прогноз с помощью predict.gam(model, newdata = new_dat), где new_dat имеет столбцы year и temp.

0 голосов
/ 30 октября 2019

Вот подход :

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(...) возвращает массив. 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)
     }
   )
0 голосов
/ 24 октября 2019

Один из подходов заключается в использовании вложенных фреймов данных. Я использовал код из этого урока .

Вы можете группировать по годам и использовать 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 (я предполагаю, что вы используете gam из пакета mgcv),Затем сопоставьте функцию модели с данными и сопоставьте функцию прогнозирования с подобранными моделями:

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)

...