我正在使用科学论文中发现的改进分位数回归函数。(来源:https://arxiv.org/pdf/2111.04805.pdf)
我尝试将这种特定方法应用于我的数据集,但我想根据数据集中的条件执行此分位数回归。这意味着我想实现类似于此处的group_by条件的东西:
qr_models = data %>%
group_by(latitude) %>%
do(model = rq(julian_day~year, tau = 1:99/100, method = "fn", data= .))
它在论文中的编码方式如下,循环是我想添加group_by的地方:
for (i in 1:n) {
alpha = i/(n+1)
alphas[i] = alpha
betas <- smrq(X,y,tau=alpha)
vals0[i] <- sum(y<(X %*% betas))
}
其中 nn <- 99
(选择的分位数分辨率);vals0 <- rep(0,n)
和alphas <- rep(0,n)
.我倾向于避免使用循环,所以我对如何做到这一点有点迷茫。
以防万一需要理解,smrq()
函数就是前面提到的论文中描述的函数,编码如下:
smrq <- function(X, y, tau){
p = ncol(X)
op.result <- optim(rep(0, p),
fn = minimize.logcosh,
method = 'BFGS',
X = X,
y = y,
tau = tau)
beta <- op.result$par
return (beta)
}
其中 X 是解释变量矩阵,y 是响应变量。
我希望它足够清楚,如果需要更多详细信息,我很乐意更新我的帖子。非常感谢宝贵的帮助。
考虑将作者的整个处理封装在用户定义的方法中,该方法接收数据(来自作者swiss
)作为输入参数以及其他变量,包括公式(来自作者的Fertility ~ .
)和响应列(来自作者的"Fertility"
)。
然后,使用group_by
传递数据子集。此外,作者for
循环可以重构为矢量化循环,例如sapply
或vapply
,因为返回是数字向量。
广义函数
minimize.logcosh <- function(par, X, y, tau) {
diff <- y-(X %*% par)
check <- (tau-0.5)*diff+(0.5/0.7)*logcosh(0.7*diff)+0.4
return(sum(check))
}
smrq <- function(X, y, tau){
p <- ncol(X)
op.result <- optim(
rep(0, p),
fn = minimize.logcosh,
method = 'BFGS',
X = X,
y = y,
tau = tau
)
beta <- op.result$par
return(beta)
}
run_smrq <- function(data, fml, response) {
x <- model.matrix(fml, data)[,-1]
y <- data[[response]]
X <- cbind(x, rep(1,nrow(x)))
n <- 99
betas <- sapply(1:n, function(i) smrq(X, y, tau=i/(n+1)))
# betas <- vapply(1:n, function(i) smrq(X, y, tau=i/(n+1)), numeric(1))
return(betas)
}
来电
测试作者示例
swiss <- datasets::swiss
smrq_models <- run_smrq(data=swiss, fml=Fertility~., response="Fertility")
dplyr
(使用group_map
)
smrq_models <- data %>%
group_by(latitude) %>%
group_map(~ run_smrq(data=., fml=julian_day~year, response="julian_day")
base
(使用by
,面向对象的包装器tapply
)
smrq_models <- by(
data,
data$latitude,
function(sub) run_smrq(data=sub, fml=julian_day~year, response="julian_day")
)