You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Tidy/Fable范式从数据框选多外生回归变量适配ARIMA模型?

在Tidy/tidyverts/Fable范式下为ARIMA模型选择多个外生回归变量

问题描述

Q:使用Tidy/tidyverts/Fable范式,如何从数据框中选择多个外生回归变量用于模型拟合,尤其是适配ARIMA()?

我搭建了一个最小可复现示例,多次尝试都失败了,显然我对rlang中的解引用、符号化、注入、拼接这些概念还没搞懂。不过最后找到了一种符合Tidy范式的方法:dat %>% model(arima=ARIMA(y~xreg(!!!xreg.syms)))。

就算这个方法能用,我也想知道它为什么有效,而其他尝试都失败了?

最小可复现代码

library(dplyr)
library(purrr)
library(tsibble)
library(fable)
library(fabletools)

set.seed(123)

tibble(
  idx=1:12,
  y=rnorm(12),
  x1=c(0,0,1,rep(0,9)),
  x2=c(rep(0,9),1,0,0)) %>%
  tsibble(index=idx) -> 
  dat
# # A tsibble: 12 x 4 [1]
# idx       y    x1    x2
# <int>   <dbl> <dbl> <dbl>
# 1     1 -0.560      0     0
# 2     2 -0.230      0     0
# 3     3  1.56       1     0
# 4     4  0.0705     0     0
# 5     5  0.129      0     0
# 6     6  1.72       0     0
# 7     7  0.461      0     0
# 8     8 -1.27       0     0
# 9     9 -0.687      0     0
# 10    10 -0.446      0     1
# 11    11  1.22       0     0
# 12    12  0.360      0     0

# 手动指定变量,可行但麻烦
dat %>% model(arima=ARIMA(y~x1+x2)) # SUCCESS

# 错误用法:用:表示变量选择
dat %>% model(arima=ARIMA(y~x1:x2)) # FAILURE

# 用xreg()手动指定,可行但同样麻烦
dat %>% model(arima=ARIMA(y~xreg(x1,x2))) # SUCCESS

# 尝试传入字符向量,失败
dat %>% as_tibble() %>% select(-idx, -y) %>% colnames() -> xreg.ch
dat %>% model(arima=ARIMA(y~xreg(xreg.ch))) # FAILURE

# 尝试传入列表,失败
dat %>% as_tibble() %>% select(-idx, -y) %>% colnames() %>% as.list() -> xreg.ls
dat %>% model(arima=ARIMA(y~xreg(xreg.ls))) # FAILURE

# 尝试传入数据框,失败
dat %>% as_tibble() %>% select(-idx, -y) -> xreg.df 
dat %>% model(arima=ARIMA(y~xreg(xreg.df))) # FAILURE

# 字符向量直接用!!!拼接,失败
dat %>% model(arima=ARIMA(y~xreg(!!!xreg.ch))) # FAILURE
# 错误提示:ARIMA(y ~ xreg("x1", "x2")) [1] invalid model formula in ExtractVars

# 尝试用vars(),失败
dat %>% model(arima=ARIMA(y~xreg(vars(x1,x2)))) # FAIL

# 传入矩阵,可行但不够优雅
dat %>% as_tibble() %>% select(-idx, -y) %>% as.matrix() -> xreg.mat
dat %>% model(arima=ARIMA(y~xreg(xreg.mat))) -> fit # SUCCESS!!
fit %>% pull(arima) %>% pluck(1, 'fit', 'par')
# # A tibble: 2 × 5
# term       estimate std.error statistic p.value
# <chr>         <dbl>     <dbl>     <dbl>   <dbl>
# 1 xreg.matx1  -0.491      0.821   -0.598    0.561
# 2 xreg.matx2  -0.0713     0.821   -0.0869   0.932

# 符号向量+!!!拼接,可行且符合Tidy范式
dat %>% as_tibble() %>% select(-idx, -y) %>% colnames() %>% syms() -> xreg.syms
dat %>% model(arima=ARIMA(y~xreg(!!!xreg.syms))) -> fit # SUCCESS!!??
fit %>% pull(arima) %>% pluck(1, 'fit', 'par')
# # A tibble: 2 × 5
# term  estimate std.error statistic p.value
# <chr>    <dbl>     <dbl>     <dbl>   <dbl>
# 1 x1     -0.491      0.821   -0.598    0.561
# 2 x2     -0.0713     0.821   -0.0869   0.932

解答

更简洁的Tidy风格写法

除了你找到的方法,还可以直接用tidyselect语法配合pick()函数,不需要手动转换符号,更符合Tidy范式:

# 选择所有以x开头的变量
dat %>% model(arima = ARIMA(y ~ xreg(pick(starts_with("x")))))

# 排除idx和y,选择剩余变量
dat %>% model(arima = ARIMA(y ~ xreg(pick(-idx, -y))))

为什么xreg(!!!xreg.syms)有效?

核心在于rlang的符号处理和拼接机制:

  1. syms(xreg.ch)把字符串向量c("x1","x2")转换成符号对象——符号是R用来代表变量名的语法元素,和你手动写x1本质一样。
  2. !!!是rlang的拼接运算符,它会把符号向量拆成单独的参数传递给xreg(),也就是xreg(!!!xreg.syms)等价于xreg(x1, x2),这正是ARIMA()能识别的格式。

其他尝试失败的原因

逐个拆解:

  • y~x1:x2::在公式里表示交互项,不是选择多个变量,模型会尝试拟合x1和x2的交互效应,而非把它们作为独立外生变量,自然报错。
  • xreg(xreg.ch)/xreg(xreg.ls):xreg()需要接收变量名(符号),而不是字符串向量或列表,R会把这些对象当成单个变量名去查找,数据里没有对应变量,直接失败。
  • xreg(xreg.df):数据框会被当成单个输入对象,模型无法解析其中的列作为独立变量,而矩阵能成功是因为xreg()支持矩阵输入,但会丢失原变量名,不够优雅。
  • xreg(!!!xreg.ch):字符串直接用!!!拼接会变成xreg("x1","x2"),模型把字符串当成字面量,而非变量名,无法解析。
  • xreg(vars(x1,x2)):vars()是tidyverse的变量选择工具,但xreg()不兼容这个语法,无法识别其返回的对象。

内容的提问来源于stack exchange,提问作者lowndrul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 08:05:14