对于线性模型,有没有办法在 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 中的统计信息(这可能会派上用场),您可以使用 purrr
和 broom
包。这是使用数据集 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")
我有一个数据 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 中的统计信息(这可能会派上用场),您可以使用 purrr
和 broom
包。这是使用数据集 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")