在 R 中的 for 循环内分组

Grouping inside of a for-loop in R

我正在使用在一篇科学论文中发现的修改后的分位数回归函数。 (来源: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))
}

其中 n 是 n <- 99(选择的分位数分辨率); vals0 <- rep(0,n)alphas <- rep(0,n)。我倾向于避免在 R 中使用循环,所以我有点不知道如何去做。

为了以防万一需要理解,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 是响应变量。

我希望它足够清楚,如果需要更多细节,我会很乐意更新我的 post。非常感谢宝贵的帮助。

考虑将作者的整个处理封装在一个 user-defined 方法中,该方法接收数据(swiss 来自作者)作为输入参数以及其他变量,包括公式(Fertility ~ . 来自作者)和回复列("Fertility" 来自作者)。

然后,使用 group_by 传递数据子集。此外,作者的 for 循环可以重构为矢量化循环,例如 sapplyvapply,因为 return 是一个数字向量。

广义函数

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 (使用 bytapply 的 object-oriented 包装器)

smrq_models <- by(
   data, 
   data$latitude, 
   function(sub) run_smrq(data=sub, fml=julian_day~year, response="julian_day")
)