如何解决在数据上迭代一个函数,然后将结果分离到不同的对象中 创建拟合模型列表在工作区中创建独特的对象对eval(bquote(lm(.(f), data = ggplot2::diamonds))))的解释
我有兴趣在 r 中迭代一些函数。
具体来说,我想使用线性模型在 diamonds
数据集上运行代码,其中 IV 为 price
并且使用变量 carat
从一个模型到另一个模型的 DV 、x
、y
和 z
。我希望将这些单独的模型存储在唯一的对象中(例如,对于 carat
,名称将是 lm_IV_price_carat
,对于 x
,对象的名称将是 ```lm_IV_price_x`` ``).
然后我想使用这些独特的对象来创建具有 lm() 对象摘要的独特对象(例如,lm_IV_price_carat
的摘要将被称为 summary_lm_IV_price_carat
,{{ 1}} 将是 lm_IV_price_x
)。
我可以在没有迭代的情况下完成这项工作,但这可以用更少的代码来完成吗?如果是这样,这将如何完成?
编辑 1:稍微更改标题并使示例更短更具体。
有人告诉我,让示例更具体是个好主意。
我想要做的是在各种不同的变量上一遍又一遍地运行相同的基本代码集,而不必每次我想更改变量时都重复和写出所有代码。我可以做得很长,但我不知道如何在 r 中以更短的方式做到这一点。我想知道是否有办法以更短的方式做到这一点。
这是我想要做的,以及相应的代码,使用长版:
(1) 创建一个通用的 lm() 对象,该对象仅在使用的 DV 方面有所不同,以 ```carat`` 开头。
summary_lm_IV_price_x
(2) 创建lm对象的通用summary()对象,以#### creates lm()
lm_IV_price <- lm(carat ~ price,data = diamonds)
开头。
carat
(3) 为这些 lm() 和 summary() 通用对象提供唯一的名称。
#### creates summary of data
summary_lm_IV_price <- summary(lm_IV_price)
(4) 使用变量 #### creates unique names for lm_IV_price
# ---- NOTE: generates name to use for object created
name_lm_IV_price <- paste("lm_IV_price","_",as.character(lm_IV_price$call$formula[[2]]),sep = "")
# ---- NOTE: creates unique object
assign(name_lm_IV_price,lm_IV_price)
#### creates unique names for summary_lm_IV_price
# ---- NOTE: generates name to use for object created
name_summary_lm_IV_price <- paste("summary_lm_IV_price",as.character(summary_lm_IV_price$call$formula[[2]]),sep = "")
# ---- NOTE: creates unique object
assign(name_summary_lm_IV_price,summary_lm_IV_price)
、x
和 y
重复步骤 1-3。请参阅下面的代码,了解我是如何长期做到这一点的(即,我复制了第一个代码集,然后使用了查找和替换)。
我想知道是否有办法使用较少的 r 代码更快地完成这项任务。
这是长版的代码:
z
解决方法
如果我理解正确,OP 想要
- 使用不同的公式拟合多个线性模型,
- 创建每个模型的摘要,
- 最后在全局环境中创建单个对象。
我的首选方法是在一个更大的数据对象(例如列表)中将结构相同的数据尽可能长时间地保存在一起,以免工作区被许多单个对象弄得混乱。但是,如果 OP 坚持可以使用 list2env()
从命名列表轻松创建单个对象。
好吧,这就是我要做的
创建拟合模型列表
# define variables
ivar <- "price"
dvars <- setdiff(names(ggplot2::diamonds),ivar)[c(1,7:9)] # carat,x,y,z
# create character vectors of formulae and names
formulae <- paste(dvars,"~",ivar)
lm_names <- sprintf("lm_IV_%s_%s",ivar,dvars)
# loop over formulae to fit models
lm_list <- lapply(formulae,function(f) eval(bquote(lm(.(f),data = ggplot2::diamonds))))
# name list elements
lm_list <- setNames(lm_list,lm_names)
lm_list
$lm_IV_price_carat
Call:
lm(formula = "carat ~ price",data = ggplot2::diamonds)
Coefficients:
(Intercept) price
0.3672972 0.0001095
$lm_IV_price_x
Call:
lm(formula = "x ~ price",data = ggplot2::diamonds)
Coefficients:
(Intercept) price
4.7531182 0.0002487
$lm_IV_price_y
Call:
lm(formula = "y ~ price",data = ggplot2::diamonds)
Coefficients:
(Intercept) price
4.7601319 0.0002478
$lm_IV_price_z
Call:
lm(formula = "z ~ price",data = ggplot2::diamonds)
Coefficients:
(Intercept) price
2.9395800 0.0001523
lm_list 是包含拟合四个模型的结果的列表。列表元素按照 OP 的要求命名。
在列表中的每个模型上应用 summary()
函数(或任何其他合适的函数,例如 coef()
)很简单:
lapply(lm_list,summary)
$lm_IV_price_carat
Call:
lm(formula = "carat ~ price",data = ggplot2::diamonds)
Residuals:
Min 1Q Median 3Q Max
-1.35765 -0.11329 -0.02442 0.10344 2.66973
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 3.673e-01 1.112e-03 330.2 <2e-16 ***
price 1.095e-04 1.986e-07 551.4 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.184 on 53938 degrees of freedom
Multiple R-squared: 0.8493,Adjusted R-squared: 0.8493
F-statistic: 3.041e+05 on 1 and 53938 DF,p-value: < 2.2e-16
$lm_IV_price_x
Call:
lm(formula = "x ~ price",data = ggplot2::diamonds)
Residuals:
Min 1Q Median 3Q Max
-9.2380 -0.4204 0.0200 0.3935 2.8574
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 4.753e+00 3.165e-03 1501.7 <2e-16 ***
price 2.487e-04 5.650e-07 440.2 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.5235 on 53938 degrees of freedom
Multiple R-squared: 0.7822,Adjusted R-squared: 0.7822
F-statistic: 1.937e+05 on 1 and 53938 DF,p-value: < 2.2e-16
$lm_IV_price_y
Call:
lm(formula = "y ~ price",data = ggplot2::diamonds)
Residuals:
Min 1Q Median 3Q Max
-9.228 -0.416 0.022 0.392 51.115
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 4.760e+00 3.460e-03 1375.8 <2e-16 ***
price 2.478e-04 6.176e-07 401.1 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.5723 on 53938 degrees of freedom
Multiple R-squared: 0.749,Adjusted R-squared: 0.7489
F-statistic: 1.609e+05 on 1 and 53938 DF,p-value: < 2.2e-16
$lm_IV_price_z
Call:
lm(formula = "z ~ price",data = ggplot2::diamonds)
Residuals:
Min 1Q Median 3Q Max
-5.8019 -0.2669 0.0090 0.2482 28.5603
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 2.940e+00 2.168e-03 1355.7 <2e-16 ***
price 1.523e-04 3.871e-07 393.6 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.3586 on 53938 degrees of freedom
Multiple R-squared: 0.7418,Adjusted R-squared: 0.7417
F-statistic: 1.549e+05 on 1 and 53938 DF,p-value: < 2.2e-16
结果又是一个命名列表。
在工作区中创建独特的对象
我将继续使用列表,但 OP 要求将单个模型存储在唯一对象中。
这可以通过
list2env(lm_list,.GlobalEnv)
在工作区中创建四个对象:
apropos("lm_IV")
[1] "lm_IV_price_carat" "lm_IV_price_x" "lm_IV_price_y" "lm_IV_price_z"
为摘要创建唯一对象有点乏味,因为我们必须重命名列表元素:
library(magrittr) # piping used to improve readability
lapply(lm_list,summary) %>%
set_names(paste0("summary_",names(.))) %>%
list2env(.GlobalEnv)
apropos("summary_lm_IV")
[1] "summary_lm_IV_price_carat" "summary_lm_IV_price_x" "summary_lm_IV_price_y"
[4] "summary_lm_IV_price_z"
对eval(bquote(lm(.(f),data = ggplot2::diamonds))))
的解释
我的第一次尝试是
lm_list <- lapply(formulae,function(f) lm(f,data = ggplot2::diamonds))
效果很好,只是公式 carat ~ price
,例如,从 lm()and
summary()` 的输出中消失了:
Call:
lm(formula = f,data = ggplot2::diamonds)
注意公式信息仍然包含在模型中,可以通过
lapply(formulae,function(f) format(terms(lm(f,data = ggplot2::diamonds))))
[[1]]
[1] "carat ~ price"
[[2]]
[1] "x ~ price"
[[3]]
[1] "y ~ price"
[[4]]
[1] "z ~ price"
John Mount 的文章 R Tip: How to Pass a formula to lm 建议使用 eval()
、bquote()
、.()
模式。
或者,wrapr::let()
也能正常工作:
lapply(dvars,function(dv) wrapr::let(c(DV = dv,IV = "price"),lm(DV ~ IV,data = ggplot2::diamonds)))
或
lapply(dvars,function(dv) wrapr::let(c(DV = dv),lm(DV ~ price,data = ggplot2::diamonds)))
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。