简单线性回归模型的迭代

时间:2021-02-09 13:21:50

标签: r loops data.table linear-regression prediction

我想拟合/训练一个预测模型并以交互方式进行,例如,我在选定时间段(此处:2020 年全年)内每 50 天训练一次我的模型。基本上我想预测第二列(DE)并使用剩余的列和参数进行预测。我的数据表可能如下所示:

set.seed(123)
days <- 50
## Create random data table: ##
dt.data <- data.table(date = seq(as.Date('2020-01-01'), by = '1 day', length.out = 366),
                      "DE" = rnorm(366, 35, 1), "Wind" = rnorm(366, 5000, 2), "Solar" = rnorm(366, 3, 2),
                      "Nuclear" = rnorm(366, 100, 5), "ResLoad" = rnorm(366, 200, 3),  check.names = FALSE)

我的数据表的日期范围、预测变量的数量和天数 (days) 总是不同的。我已经对整个数据表进行了一次模型拟合/训练,但我不知道如何每 50 天迭代一次?在这里您可以看到我的模型拟合线性模型的代码片段:

v.trainDate <- dt.data$date
## Delete column "date" of train data for model fitting: ##
dt.data <- dt.data[, c("date") := NULL]

## MODEL FITTING: ##
## Linear Model: ##
lmModel <- stats::lm(DE ~ .-1, data = dt.data)

## Train PREDICTION with lmModel: ##
dt.data$prediction <- stats::predict.glm(lmModel, dt.data)
## Add date columns to dt.train: ##
dt.data <- data.table(date = v.trainDate, dt.data)

最后我想要的是,我首先用我的数据训练模型,从 2020-01-012020-02-20(前 50 天)并预测 DE 的价格我的数据表的前五十个条目的模型 lmModel。下一次运行应该是从 2020-02-202020-04-10(接下来的 50 天)训练我的模型,并预测这个新 50 天的值。这应该在 2020 年 12 月的最后一天之前完成。最后,我需要一个名为 prediction 的列,如您在我的代码片段中所见,但该列应包含 {{1} } 价格。

我还想在每次迭代后将变量重要性保存在某处?这样我就可以看到在前 50 天等中哪个变量对 DE 价格的影响最大。有谁知道这是如何工作的?

2 个答案:

答案 0 :(得分:1)

这是一种方法,使用嵌套数据框和 map() 函数的优良特性。基本上首先创建一个开始日期的数据集,然后选择与该开始日期相关的数据,然后运行回归并提取结果。最终输出显示为一个数据集,其中行代表样本的第一个日期,列代表预测数据的日期。

library(tidyverse)
days <- 50
set.seed(123)
## Create random data table: ##
data <- tibble(date = seq(as.Date('2020-01-01'), by = '1 day', length.out = 366),
                  "DE" = rnorm(366, 35, 1), "Wind" = rnorm(366, 5000, 2), "Solar" = rnorm(366, 3, 2),
                  "Nuclear" = rnorm(366, 100, 5), "ResLoad" = rnorm(366, 200, 3),  check.names = FALSE)


data_out <- tibble(train_start_date= tail(data$date, -50)) %>% 
  mutate(data = map(train_start_date, ~filter(data, date >=.x) %>% 
                      head(50)),
         lmModel =map(data, ~stats::lm(DE ~ .-1, data = .x)),
         prediction= map2(lmModel, data,  ~tibble(train_end_date=max(.y$date), 
                                                  prediction=predict(.x), 
                                                 prediction_date = .y$date))) %>% 
  select(train_start_date, prediction) %>% 
  unnest(prediction) %>% 
  mutate(train_n_days = as.integer(train_end_date-train_start_date)+1) %>% 
  select(train_start_date, train_end_date, train_n_days, prediction_date, prediction)

data_out
#> # A tibble: 14,575 x 5
#>    train_start_date train_end_date train_n_days prediction_date prediction
#>    <date>           <date>                <dbl> <date>               <dbl>
#>  1 2020-02-20       2020-04-09               50 2020-02-20            35.0
#>  2 2020-02-20       2020-04-09               50 2020-02-21            35.0
#>  3 2020-02-20       2020-04-09               50 2020-02-22            35.1
#>  4 2020-02-20       2020-04-09               50 2020-02-23            35.2
#>  5 2020-02-20       2020-04-09               50 2020-02-24            34.6
#>  6 2020-02-20       2020-04-09               50 2020-02-25            35.2
#>  7 2020-02-20       2020-04-09               50 2020-02-26            35.0
#>  8 2020-02-20       2020-04-09               50 2020-02-27            35.0
#>  9 2020-02-20       2020-04-09               50 2020-02-28            35.1
#> 10 2020-02-20       2020-04-09               50 2020-02-29            35.1
#> # … with 14,565 more rows

reprex package (v1.0.0) 于 2021 年 2 月 15 日创建

答案 1 :(得分:1)

下面的 calclm 函数计算预测值,calcImportance 函数计算变量重要性。

by=seq_len(nrow(dt.data)) %/% days 参数使用 data.table 将数据集拆分为 days 块并将前面的函数应用于每个块:

library(data.table)
library(caret)

## Create random data table: ##
dt.data <- data.table(date = seq(as.Date('2020-01-01'), by = '1 day', length.out = 366),
                      "DE" = rnorm(366, 35, 1), "Wind" = rnorm(366, 5000, 2), "Solar" = rnorm(366, 3, 2),
                      "Nuclear" = rnorm(366, 100, 5), "ResLoad" = rnorm(366, 200, 3),  check.names = FALSE)

set.seed(123)
days <- 50

# Prediction calculation
calcPred <- function(data) {
  lmModel <- stats::lm(DE ~ .-1-date, data = data)
  stats::predict.glm(lmModel, data)
}

# Importance calculation
calcImportance <- function(data) {
  lmModel <- stats::lm(DE ~ .-1-date, data = data)
  terms <- attr(lmModel$terms , "term.labels")
  varimp <- caret::varImp(lmModel)
  importance <- data[,.(date,imp = t(varimp))]
}

importance.data <- data.table::copy(dt.data)
importance.data[,calcImportance(.SD),by=seq_len(nrow(dt.data)) %/% days]
#>      seq_len       date imp.Wind imp.Solar imp.Nuclear imp.ResLoad
#>   1:       0 2020-01-01 4.598201 2.4726894   0.7993097   1.7153244
#>   2:       0 2020-01-02 4.598201 2.4726894   0.7993097   1.7153244
#>   3:       0 2020-01-03 4.598201 2.4726894   0.7993097   1.7153244
#>   4:       0 2020-01-04 4.598201 2.4726894   0.7993097   1.7153244
#>   5:       0 2020-01-05 4.598201 2.4726894   0.7993097   1.7153244
#>  ---                                                              
#> 362:       7 2020-12-27 1.093177 0.2558265   0.1610440   0.5383146
#> 363:       7 2020-12-28 1.093177 0.2558265   0.1610440   0.5383146
#> 364:       7 2020-12-29 1.093177 0.2558265   0.1610440   0.5383146
#> 365:       7 2020-12-30 1.093177 0.2558265   0.1610440   0.5383146
#> 366:       7 2020-12-31 1.093177 0.2558265   0.1610440   0.5383146

dt.data[,c('prediction'):=calcPred(.SD),by=seq_len(nrow(dt.data)) %/% days]

dt.data
#>            date       DE     Wind      Solar   Nuclear  ResLoad prediction
#>   1: 2020-01-01 36.51972 5000.608  1.4283653  92.19844 200.1163   35.02625
#>   2: 2020-01-02 34.96544 4999.235  0.3860045  92.29005 203.2613   34.96200
#>   3: 2020-01-03 35.16448 5002.232 -1.4450524 100.32920 202.5225   35.67255
#>   4: 2020-01-04 36.07978 5000.564 -0.9137483  98.07459 206.3788   35.13325
#>   5: 2020-01-05 35.10967 4997.606  4.9788029 101.27625 201.8148   34.29788
#>  ---                                                                      
#> 362: 2020-12-27 34.98190 4997.936  2.6117305  98.33027 195.1352   34.80871
#> 363: 2020-12-28 35.16974 4998.799  1.0776123 108.26064 195.2474   35.01232
#> 364: 2020-12-29 35.37956 4998.651  3.9252237 102.87948 201.0266   35.09362
#> 365: 2020-12-30 35.51517 4999.428  5.9747031  92.38721 196.4204   34.60962
#> 366: 2020-12-31 33.53278 5001.911  3.5062344  93.60744 197.5292   34.85689