我有一个自定义函数,其中包括根据指定的字符串输入创建回归公式并运行回归(brm,但对于Basic lm应该是类似的工作方式):

model_predict <- function(.data, dep_var, model ...) {
    form <- as.formula(str_glue("{dep_var} ~ {model}"))
    form_vars <- all.vars(form)

    ... # some other stuff

    fit <- brm(form, .data, ...)

    ... # some other stuff
}

作为更大的工作流程的一部分,我使用它来适应大量预先指定的模型.

有时,model个变量中的一些变量是因素变量,有时这些因素在数据中只有一个级别.这会导致在try 拟合模型时出现contrasts can be applied only to factors with 2 or more levels错误.

由于较大的工作流程,并且任何给定迭代的数据和模型是否会遇到此问题并不总是很清楚,所以当这些变量在相关数据子集中只有一个级别时,我不愿手动从指定的模型中删除这些因子变量.

这将是最简单的解决方案,但我不确定它是否存在.

或者,我希望有一个自动化的解决方案,它可以识别何时出现单因素水平的情况,并在出现时从公式中删除相关变量(可能也会给出警告消息),例如:

# main formula
form
> outcome ~ predictor_1 + predictor_2 * interactor

# Desired outputs...
# if predictor_1 has only one level in data
> outcome ~ predictor_2 * interactor

# if predictor_2 has only one level in data
> outcome ~ predictor_1

# if interactor has only one level in data
> outcome ~ predictor_1 + predictor_2

我try 了建议的tryCatch,但虽然这 suppress 了contrasts...错误,但它返回NULL,而不是忽略有问题的变量的拟合模型,这正是我需要的.

此外,有时这些变量在公式中有+,有时有*作为交互影响,这使得dynamically building the formula变得困难.

推荐答案

像这样的事情应该会奏效:

# For pipe operator
library(magrittr)

# Define function for updating the model
update_formula <- function(data, dep_var, model) {
  # Extract model variables
  model_vars <- stringr::str_split_1(model, '\\+|\\*|:') %>% 
    stringr::str_trim()
  
  model_terms <- stringr::str_split_1(model, '\\+') %>% 
    stringr::str_trim()
  
  # Get the number of levels for all factor variables
  lev_leng <- .data %>% 
    dplyr::select(where(is.factor) & any_of(model_vars)) %>% 
    purrr::map_int(
      ~ length(levels(droplevels(.x)))
    )
  
  # Check if length is one
  invalid <- names(which(lev_leng == 1))
  
  # If any is invalid, it will have length > 0
  if (length(invalid) != 0) {
    for (i in invalid) {
      if (any(stringr::str_detect(model_terms, paste0('\\*[:space:]?', i)))) {
        # Remove interactor from formula
        model_terms <- stringr::str_remove(
          model_terms,
          paste0('[\\*,:]?[:space:]?',i,'[:space:]?[\\*,:]?')
        )
      } else{
        # Remove entire term from formula
        model_terms <- model_terms[stringr::str_detect(model_terms, i, T)]
      }
    }
    model <- stringr::str_flatten(model_terms, '+')
  }
  # Define the new formula
  as.formula(glue::glue('{dep_var} ~ {model}'))
}


# Dep var defition
dep_var <- 'y'
# Model example
model <- "predictor_1 + predictor_2 * interactor"

# Example predictor_1
.data <- tibble::tibble(
  y = runif(10),
  predictor_1 = factor(1),
  predictor_2 = factor(letters[1:10]),
  interactor  = factor(letters[1:10])
)

# Update model
form <- update_formula(.data, dep_var, model)
form
#> y ~ predictor_2 * interactor
#> <environment: 0x0000015b95006a58>

# Fit the model
fit <- lm(form, .data)

# Example predictor_2
.data <- tibble::tibble(
  y = runif(10),
  predictor_1 = runif(10),
  predictor_2 = factor(letters[rep(1, 10)]),
  interactor  = factor(letters[1:10])
)

form <- update_formula(.data, dep_var, model)
form
#> y ~ predictor_1
#> <environment: 0x0000015b95cdd218>

# Example interactor
.data <- tibble::tibble(
  y = runif(10),
  predictor_1 = runif(10),
  predictor_2 = factor(letters[1:10]),
  interactor  = factor(letters[rep(1, 10)])
)

form <- update_formula(.data, dep_var, model)
form
#> y ~ predictor_1 + predictor_2
#> <environment: 0x0000015b96072878>

# Example predictor_1 & interactor
.data <- tibble::tibble(
  y = runif(10),
  predictor_1 = factor(10),
  predictor_2 = factor(letters[1:10]),
  interactor  = factor(letters[rep(1, 10)])
)

form <- update_formula(.data, dep_var, model)
form
#> y ~ predictor_2
#> <environment: 0x0000015b9669d448>

创建于2023-06-13年第reprex v2.0.2

R相关问答推荐

如何提高以键ID为列的表中键查找的效率?

在数据表中呈现数学符号

根据shiny 应用程序中的数字输入更改图标 colored颜色

R函数‘paste`正在颠倒其参数的顺序

根据类别合并(汇总)某些行

将重复项转换为NA

跨列查找多个时间报告

在带有`R`中的`ggmosaic`的马赛克图中使用图案而不是 colored颜色

如何移除GGPlot中超出与面相交的任何格网像元

如何在PrePlot()中将多个元素设置为斜体

在点图上绘制置信度或预测区间ggplot2

如何将这个小列表转换为数据帧?

将摘要图添加到facet_WRAP gglot的末尾

如何使用字符串从重复的模式中提取多个数字?

使用ggplot2中的sec_axis()调整次轴

变长向量的矢量化和

如何在使用因子时获得Sankey图的Scale_Fill_Viridis的全范围

构建一个6/49彩票模拟系统

使用其他DF中的文件名将列表中的每个元素保存到文件中

无法保存gglot的所有pdf元素