r语言 - 使用 'model' 函数调用模型/变量进行预测时如何使用字符值?



我的目标是创建一个函数,输入您想要预测的变量,然后对多种类型的模型(即Naive、ETS、Mean(进行交叉验证,然后使用"pull"函数,我将提取RMSE最低的模型,然后我将预测出最好的模型。

然而,我在倒数第二行遇到了问题,在预测时使用字符值"best.model"作为模型的输入。(错误在代码下面,您可以自己运行(。

以下是更有意义的代码:

library(fpp3)
tsibble <- prices
function.fc <- function (variable) {
## cross validation models
cv.fit <- tsibble %>%
select(year, !!sym(variable)) %>%
stretch_tsibble(.init = 180, .step = 1) %>%
filter(.id != max(.id)) %>%
model(
MEAN(!!sym(variable)),
NAIVE(!!sym(variable))
) 
## cv forecasts
cv.fc <- cv.fit %>%
forecast(h = 1)
## cv accuracy
cv.accuracy <- cv.fc %>%
accuracy(tsibble)
## pulls out the name of the best model
best.model <- cv.accuracy %>%
select(.model, .type, RMSE) %>%
arrange(RMSE) %>%
filter(row_number(RMSE) == 1) %>%
pull(.model)
## pulls out 1 step forecast 
fc <- model(.data = tsibble, noquote(best.model)) %>%
forecast(h = 1)

return(fc)
}

function.fc("copper")
Error: Model definition(s) incorrectly created: noquote(best.model) Check that specified model(s) are model definitions. Run `rlang::last_error()` to see where the error occurred

正如你所看到的,我已经尝试过使用"unquote"函数,但这仍然不起作用。有人对使用什么有什么建议吗?我一直在努力寻找其他有问题的帖子。

在函数的末尾,best.model是一个字符串。例如,如果是variable = "copper",那么函数将生成best.model = "NAIVE(copper)"model()函数需要提供一个模型定义,而不是字符串。您可以使用rlang::parse_expr()将字符串解析为代码,然后使用rlang::eval_tidy()对其进行求值以生成模型定义。

library(rlang)
library(fpp3)
#> ── Attaching packages ──────────────────────────────────────────── fpp3 0.4.0 ──
#> ✓ tibble      3.1.0          ✓ tsibble     1.0.0     
#> ✓ dplyr       1.0.5          ✓ tsibbledata 0.3.0     
#> ✓ tidyr       1.1.3          ✓ feasts      0.2.1.9000
#> ✓ lubridate   1.7.10         ✓ fable       0.3.0.9000
#> ✓ ggplot2     3.3.3
best.model <- "NAIVE(copper)"
best.model <- eval_tidy(parse_expr(best.model))
best.model
#> <RW model definition>
model(prices, best.model)
#> # A mable: 1 x 1
#>   best.model
#>      <model>
#> 1    <NAIVE>

创建于2021-05-11由reprex包(v1.0.0(

这里有一个解决方案,它采用了一种稍微不同的方法,首先定义一个可供选择的命名模型列表,然后使用best.model从列表中进行选择。这通常比陷入非标准评估的困境要好。还要注意,我已经使用了{{来"管道"未引用的参数。您会注意到我还更改了一些对象名称。这是因为您通常应该在对象名称中避免使用.,以避免与R.中面向对象编程的S3系统混淆

library(fpp3)
my_forecast <- function(data, variable) {

# Define a list of models with sensible names
models <- list(
mean = fable::MEAN,
naive = fable::NAIVE
)

## cross validation models
cv_fit <- data %>%
select(year, {{ variable }}) %>%
stretch_tsibble(.init = 180, .step = 1) %>%
filter(.id != max(.id)) %>%
model(
mean = models$mean({{ variable }}),
naive = models$naive({{ variable }})
) 

## cv forecasts
cv_fc <- cv_fit %>%
forecast(h = 1)

## cv accuracy
cv_accuracy <- cv_fc %>%
accuracy(data)

## pulls out the name of the best model
best_model <- cv_accuracy %>%
select(.model, .type, RMSE) %>%
arrange(RMSE) %>%
filter(row_number() == 1) %>%
pull(.model)

## pulls out 1 step forecast 
fc <- data %>% 
model("{best_model}" := models[[best_model]]({{ variable }})) %>%
forecast(h = 1)

fc

}
my_forecast(prices, copper)
#> # A fable: 1 x 4 [1Y]
#> # Key:     .model [1]
#>   .model  year       copper .mean
#>   <chr>  <dbl>       <dist> <dbl>
#> 1 naive   1998 N(2.6, 0.69)  2.59

创建于2021-05-11由reprex包(v2.0.0(

最新更新