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

在GLMM中如何将循环日期作为二次固定效应纳入模型?

在GLMM中实现循环日期的非线性(二次/高阶)效应

核心问题分析

你的尝试存在两个关键错误:

  1. 建模公式错误:poly((Date_sin + Date_cos), 2) 将正弦和余弦值相加后做多项式变换,完全丢失了循环变量的二维极坐标结构,把环形数据压缩成一维,无法捕捉真实的循环非线性趋势。
  2. 预测逻辑错误:用ggpredict同时遍历Date_sin和Date_cos的所有取值,会生成大量不可能存在的组合(比如sin=0.9同时cos=0.9,不符合sin²+cos²=1的约束),导致逆变换得到的JulianDay完全无效,最终绘图结果混乱。

正确实现方案

下面提供两种可靠的方法,均可在GLMM中实现循环日期的非线性效应:

方法1:使用循环B样条(最简洁推荐)

直接对JulianDay使用循环B样条(splines::bs(..., bs="cc")),它天生支持循环结构,能自动捕捉非线性循环趋势,无需手动处理sin/cos变换:

library(tidyverse) 
library(glmmTMB) 
library(ggeffects)
library(splines)

data(airquality)
airquality$Date = as.Date(paste0("2018-", airquality$Day, "-", airquality$Month)) 
airquality$JulianDay = yday(airquality$Date)
airquality = airquality %>% drop_na(Date, Ozone) # 同时删除Ozone缺失值,避免模型报错

# 使用循环B样条构建模型(df=4控制复杂度,可根据需求调整)
Mod_cyclic_spline = glmmTMB(Ozone ~ bs(JulianDay, bs="cc", df=4),
                            data = airquality,
                            family = poisson)

# 预测完整JulianDay序列的结果
pred_spline = ggpredict(Mod_cyclic_spline, terms = "JulianDay [all]")

# 绘图
ggplot(pred_spline, aes(x, predicted)) +   
  geom_line(color="blue") +
  labs(x="Julian Day", y="Predicted Ozone")

方法2:手动构建sin/cos的非线性项

如果坚持手动用sin/cos编码循环变量,需要同时纳入它们的一次、二次项以及交互项,来捕捉二维平面上的非线性趋势;且预测时必须基于真实存在的sin/cos组合(从完整JulianDay序列生成对应的值):

# 重新构建循环变量
airquality$Date_cos = cos(airquality$JulianDay*(2*pi/365)) 
airquality$Date_sin = sin(airquality$JulianDay*(2*pi/365))

# 构建包含非线性项的模型:一次项+二次项+交互项
Mod_cyclic_poly = glmmTMB(Ozone ~ Date_cos + Date_sin + I(Date_cos^2) + I(Date_sin^2) + Date_cos:Date_sin,
                          data = airquality,
                          family = poisson)

# 生成完整的JulianDay序列(1-365),计算对应的sin/cos
new_data = tibble(JulianDay = 1:365) %>%
  mutate(Date_cos = cos(JulianDay*(2*pi/365)),
         Date_sin = sin(JulianDay*(2*pi/365)))

# 预测并整合结果
pred_poly = predict(Mod_cyclic_poly, newdata = new_data, type = "response")
new_data$predicted = pred_poly

# 绘图
ggplot(new_data, aes(JulianDay, predicted)) +   
  geom_line(color="red") +
  labs(x="Julian Day", y="Predicted Ozone")

结果说明

  • 循环样条方法(方法1):代码简洁,自动处理循环边界(1月1日和12月31日的效应连续),调整df参数即可控制非线性复杂度。
  • 手动sin/cos方法(方法2):更灵活,适合需要自定义非线性结构的场景,但需确保纳入足够的项(二次项+交互项)来捕捉趋势。

两种方法的预测结果都会呈现合理的循环非线性趋势,不会出现你之前的混乱情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 19:53:12