我正在尝试将“每日时间”用作模型中的自变量。由于时间是一个循环变量,因此我将其转换为(sin(pi * hour / 12),cos(pi * hour / 12))。
我四处搜寻,但我仍然不知道如何用(sin,cos)格式的向量/元组值在R中创建列。我不知道lm,glm,glm.nb(MASS)和glmer(lme4)模型是否可以支持此类数据。
不好意思,我是这里的新手。如果向量类型变量不应该包含在回归模型中,那么我将去交叉验证(统计)以获取有关处理循环变量的建议。请帮助并分享您的经验,谢谢!
答案 0 :(得分:0)
这是一个很好的问题。
在内部,R使用矩阵将模型拟合到数据中。您不必生成模型作为元组的函数,而需要生成一个块矩阵;例如,这就是样条线的实现方式。
在您的示例中,一列包含sin(x)
,另一列cox(x)
,并且这些块用class属性标记;内部管理此对象的功能是makepredictcall
和predict
。
任何使用标准model.frame / model.matrix处理的模型都应与此兼容。
sincos <- function(x, period=168/2/pi) {
structure(cbind(`_sin`=sin(x/period),
`_cos`=cos(x/period)),
class="sincos",
period=period)
}
在这里,我们将类别和句点设置为属性。
makepredictcall.sincos <- function(var, call){
if (as.character(call)[1L] != "sincos")
return(call)
call["period"] <- attr(var, "period")
call
}
根据需要在通话中设置时间段。
predict.sincos <- function(object, newx, ...)
{
if(missing(newx))
return(object)
sincos(newx, period=attr(object, "period"))
}
使用来自拟合模型的时间段调用我们的函数。
以下是使用lm
的简短示例:
#FAKE DATA EXAMPLE
N <- 1000
hr <- sample(168, N, replace = TRUE)
Y = 5 + sinpi(hr * 2/168) + cospi(hr * 2/168) + rnorm(N)
lm(Y~sinpi(hr*2/168)+cospi(hr*2/168))
#>
#> Call:
#> lm(formula = Y ~ sinpi(hr * 2/168) + cospi(hr * 2/168))
#>
#> Coefficients:
#> (Intercept) sinpi(hr * 2/168) cospi(hr * 2/168)
#> 5.0078 1.0243 0.9637
我们的自定义函数完全匹配:
lm(Y~sincos(hr))
#>
#> Call:
#> lm(formula = Y ~ sincos(hr))
#>
#> Coefficients:
#> (Intercept) sincos(hr)_sin sincos(hr)_cos
#> 5.0078 1.0243 0.9637
其他函数也将能够看出这两列是模型中的单个术语:
anova(lm(Y~sincos(hr)))
#> Analysis of Variance Table
#>
#> Response: Y
#> Df Sum Sq Mean Sq F value Pr(>F)
#> sincos(hr) 2 1051.05 525.53 553.24 < 2.2e-16 ***
#> Residuals 997 947.06 0.95
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
如果其他人觉得有帮助,我会在接下来的几天内将其添加到stackoverflow
包中。