GAM模型构建报错求助:对因子类型的0时与12时做平滑处理
GAM模型对小时哑变量平滑报错的问题解决
问题背景
构建GAM模型时,将数据集中的小时设为因子类型,生成哑变量后对hour0(0时)和hour12(12时)使用s()平滑函数,始终报错,无法定位原因。
相关代码与数据结构
数据处理代码
data$time = substr(data$x, 1, 16) data$start_time <- as.POSIXct(data$start_time, format = "%d.%m.%Y %H:%M", tz = "UTC") data = subset(data, select = -c(x, y)) data$hour <- hour(data$start_time) head(data) df = data %>% mutate(data_aggregate = floor_date(time, unit = "hour")) %>% group_by(data_aggregate) %>% summarise(W = sum(WindInfeed, na.rm = TRUE)) df1 <- df %>% mutate(hour = as.factor(hour(data_aggregate))) # 生成哑变量矩阵 df1$hour <- as.factor(df1$hour) dummy_matrix <- model.matrix(~hour-1, data = df1) df_new <- cbind(dummy_matrix, df1) # 尝试构建GAM模型(报错代码) gam.lm2 <- gam(W~s(hour0) + s(hour12), data = df_new)
数据结构示例
df1关键列的前几行:
structure(list(data_aggregate = structure(c(1640995200, 1640998800, 1641002400, 1641006000, 1641009600, 1641013200), tzone = "UTC", class = c("POSIXct", "POSIXt")), hour = structure(1:6, levels = c("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23"), class = "factor")), row.names = c(NA, -6L), class = c("tbl_df", "tbl", "data.frame"))
df_new哑变量列的前几行:
structure(list(hour0 = c(1, 0, 0, 0, 0, 0), hour2 = c(0, 0, 1, 0, 0, 0)), row.names = c("1", "2", "3", "4", "5", "6"), class = "data.frame")
报错原因
hour0和hour12是二元哑变量,取值仅为0或1。GAM的s()平滑函数需要变量具备足够多的不同取值(连续变量或多水平分类变量)才能拟合平滑效应,二元变量的自由度完全无法支撑平滑函数的拟合逻辑,因此必然报错。
解决方案
根据需求可选择以下调整方式:
1. 直接用线性项建模(无需平滑)
如果仅需估计0时和12时对W的独立影响,直接使用哑变量的线性项即可:
# 方式1:用已生成的哑变量 gam.lm2 <- gam(W ~ hour0 + hour12, data = df_new) # 方式2:直接用原hour因子更简洁,自动生成参考水平对比 gam.lm2 <- gam(W ~ hour, data = df1)
2. 对小时的周期效应做整体平滑
如果想捕捉小时的周期性平滑变化(比如0时和23时效应相近),将hour转为连续整数后使用循环立方样条(bs="cc"),适配小时的周期特性:
# 将hour因子转为整数,用循环平滑 gam.lm2 <- gam(W ~ s(as.integer(hour), bs = "cc", k = 10), data = df1)
其中k为平滑自由度,可根据数据调整,建议取值5-15。
3. 特定小时的局部平滑
若仅关注0时和12时附近的效应,可构建连续小时变量并结合受限平滑,但这种场景下更推荐方式2的周期平滑,更符合小时变量的本质特性。
内容的提问来源于stack exchange,提问作者momo
相关产品推荐
相关产品推荐

