我的问题现在已经有几年了,我想添加最终对我最有效的解决方案。
首先,使用 mgcv 来拟合我的问题中描述的模型是不可能的。
有一段时间我使用了一个两阶段的过程。
model1 = gam(
y ~ s(day_in_year, k=52, bs='cc')
+ s(day_in_year, k=52, bs='cc')
+ as.factor(day_in_week)
, knots=list(
day_in_year=c(0, 366)
, day_in_week=c(0,7)
)
, data = data
)
# get_weekday_offset gets the coefficients for each weekday and normalizes them to have mean 0
data$weekday_offset = get_weekday_offset(model1)[data$day_in_week]
model2 = gam(
y ~ s(day_in_year, k=52, bs='cc')
+ s(day_in_year, k=52, bs='cc')
+ s(day_in_year, k=52, bs='cc', by=weekday_offset)
+ as.factor(day_in_week)
, knots=list(
day_in_year=c(0, 366)
, day_in_week=c(0,7)
)
, data = data
)
第二个模型的形式是“y ~ f(年中的天) + g(年中的天) * h(周中的天)”,但h是一个固定函数,不适合第二个模型中的数据,而是基于最适合model1
。这样做的明显缺点是 mgcv 需要运行两次,并且第一次运行的几乎所有信息(工作日的系数除外)都被丢弃。
我最终放弃这个模型的原因是除了振幅的变化之外,一年中形状确实发生了一些变化,所以我最终决定看起来像这样。
gam(
y ~ s(day_in_year, k=52, bs='cc')
+ s(day_in_year, k=10, bs='cc', by=as.factor(day_in_week)
+ as.factor(day_in_week)
, knots=list(
day_in_year=c(0, 366)
, day_in_week=c(0,7)
)
, data = data
)
我放弃了s
工作日的数据,因为我已经证明使用每周模式的最大自由度来证明数据是合理的,并且我在工作日和一年中的某一天(s(day_in_year, k=12, bs='cc', by=as.factor(day_in_week)
)之间添加了交互效应,这估计了一条单独的季节性曲线对于每个工作日,但是由于它包含的自由度数量远低于季节性术语s(day_in_year, k=52, bs='cc')
,因此我在尝试te
术语时不会遇到问题。