对于线性模型,有没有办法在 r 中循环列名(不是数字)?

Is there a way to loop through column names (not numbers) in r for linear models?

我有一个数据 sheet,其中包含 40 个数据列(40 种不同的营养素),还有用于地块编号和因子的附加列。我想自动遍历每个列名并为每个列名生成一个线性模型和摘要。数据列从第 10 列开始。

for(i in 10:ncol(df)) {       # for-loop over columns
  mod2<-aov(i~block+tillage*residue+Error(subblock),data=df)
  summary(mod2)
}

当前正在产生错误 Error in model.frame.default(formula = i ~ subblock, data = df, drop.unused.levels = TRUE) : variable lengths differ (found for 'subblock') 可变长度是一致的,所以我想我循环不正确。

数据看起来类似于下面(开头有更多分类列),营养列从第 10 列开始。

block tillage residue subblock nutrient 1 nutrient 2 etc.
b1 NT NR s1 0.5 0.6

一般来说,使用 dput() post 数据样本会很有帮助。如果没有,我将使用内置数据集 mtcars 向您展示如何使用 formula():

来完成您正在做的事情
head(mtcars)

#                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
# Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
# Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
# Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
# Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
# Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
# Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1

# Select columns
desired_columns  <- names(mtcars)[!names(mtcars)=="mpg"]

for (column in desired_columns){
    this_formula = formula(paste("mpg ~ ", column))
    print(summary(lm(this_formula, data = mtcars)))
}

这将为数据中的每个 var 输出 lm(mpg ~ var)。关键是 paste() 语句,它将表达式构建成一个字符串,然后 formula() 将其变成一个公式对象 希望您能看到如何将其应用于您的数据。

这是一个简单的基本解决方案:

model <- list()
model_summary <- list()
for(i in 10:ncol(df)) {       # for-loop over columns
  col <- colnames(df)[i]
  formula <- as.formula(paste0(col,"~block+tillage*residue+Error(subblock)"))
  model[[i-9]] <-aov(formula,data=df)
   model_summary [[i-9]]<-summary(model[[i-9]])
}

只需在每次迭代时使用 i-column

的名称创建一个新公式

编辑

正如@Ben Bolker 在评论中所建议的那样,您可以通过更改

以更清晰、更简单的方式使用 reformulate 获得相同的结果
formula <- as.formula(paste0(col,"~block+tillage*residue+Error(subblock)"))

formula <- reformulate(response=col,"block+tillage*residue+Error(subblock)")

您不需要循环。您可以将矩阵传递给公式的 LHS:

dep <- names(iris)[names(iris) != "Species"]
f <- as.formula(sprintf("cbind(%s) ~ Species", paste(dep, collapse = ",")))

summary(lm(f, data = iris))

Purrr 解法:

没有 MWE 很难帮到你。我的方法是将您的数据集拆分为一个因变量数据集和一个自变量数据集。然后将每个因变量放入一个列表中并附加独立数据集。然后您可以“循环”遍历每个列表并应用您喜欢的回归。

df <- mtcars

df_independent <- df %>%
  as_tibble() %>%
  # select independent variables
  select(9:10)

df_dependent <- df %>%
  as_tibble() %>%
  # select all dependent variables and store each column in a list
  select(1:8) %>%
  as.list() %>%
  map(as_tibble) %>%
  map(~ cbind(.x, df_independent))


df_dependent %>%
 # df_independent %>% colnames() %>% paste0(".x$",., collapse ="+")
  map(~ lm(.x$value ~ .x$am + .x$gear)) %>%
  map(summary)

如果您想要 table 中的统计信息(这可能会派上用场),您可以使用 purrrbroom 包。这是使用数据集 mtcars:

的示例

代码

library(tidyr)
library(purrr)
library(broom)

formula <- lapply(colnames(mtcars)[3:ncol(mtcars)], function(x) as.formula(paste0(x, " ~ cyl")))

names(formula) <- format(formula)

table <- formula %>% map(~aov(.x, mtcars)) %>% map_dfr(tidy, .id="model")

输出

> head(table)
# A tibble: 6 x 7
  model      term         df     sumsq     meansq statistic   p.value
  <chr>      <chr>     <dbl>     <dbl>      <dbl>     <dbl>     <dbl>
1 disp ~ cyl cyl           1 387454.   387454.        131.   1.80e-12
2 disp ~ cyl Residuals    30  88731.     2958.         NA   NA       
3 hp ~ cyl   cyl           1 100984.   100984.         67.7  3.48e- 9
4 hp ~ cyl   Residuals    30  44743.     1491.         NA   NA       
5 drat ~ cyl cyl           1      4.34      4.34       28.8  8.24e- 6
6 drat ~ cyl Residuals    30      4.52      0.151      NA   NA    

尝试

formula <- lapply(colnames(df)[10:ncol(df)], function(x) as.formula(paste0(x, " ~ block + tillage * residue + Error(subblock)")))

names(formula) <- format(formula)

table <- formula %>% map(~aov(.x, df)) %>% map_dfr(tidy, .id="model")