Pat*_* W. 3 for-loop group-by r idiomatic dplyr
任何人都可以建议dplyr回答以下问题吗?
按国家/地区分割data.frame,并在每个子集上创建线性回归模型
为完整起见,链接中的问题和答案包含在下面.
作为参考,这是Josh的问题:
我有一个来自世界银行的数据框架,看起来像这样;
country date BirthRate US.
4 Aruba 2011 10.584 25354.8
5 Aruba 2010 10.804 24289.1
6 Aruba 2009 11.060 24639.9
7 Aruba 2008 11.346 27549.3
8 Aruba 2007 11.653 25921.3
9 Aruba 2006 11.977 24015.4
Run Code Online (Sandbox Code Playgroud)
总而言之,在这个数据框中有70个国家的子集,我想对其进行线性回归.如果我使用以下内容,我会为一个国家获得一个不错的lm;
andora = subset(high.sub, country == "Andorra")
andora.lm = lm(BirthRate~US., data = andora)
anova(andora.lm)
summary(andora.lm)
Run Code Online (Sandbox Code Playgroud)
但是当我尝试在for循环中使用相同类型的代码时,我会收到一个错误,我将在代码下面打印出来;
high.sub = subset(highInc, date > 1999 & date < 2012)
high.sub <- na.omit(high.sub)
highnames <- unique(high.sub$country)
for (i in highnames) {
linmod <- lm(BirthRate~US., data = high.sub, subset = (country == "[i]"))
}
#Error message:
Error in lm.fit(x, y, offset = offset, singular.ok = singular.ok, ...) :
0 (non-NA) cases
Run Code Online (Sandbox Code Playgroud)
如果我可以让这个循环运行,我理想的是将每个模型的系数和更好的r平方值附加到空data.frame.任何帮助将不胜感激.
作为参考,这里是jlhoward的答案(结合BondedDust的评论)利用这个优秀问题中的*apply函数: R分组函数:sapply vs. lapply与apply.vs. tapply vs. by vs. aggregate
models <- sapply(unique(as.character(df$country)),
function(cntry)lm(BirthRate~US.,df,subset=(country==cntry)),
simplify=FALSE,USE.NAMES=TRUE)
# to summarize all the models
lapply(models,summary)
# to run anova on all the models
lapply(models,anova)
#This produces a named list of models, so you could extract the model for Aruba as:
models[["Aruba"]]
Run Code Online (Sandbox Code Playgroud)
从中返回列表dplyr是不可能的.如果你只是需要截距和斜率@jazzurro的答案是这样的,但如果你需要整个模型你需要做类似的事情
library(dplyr)
models <- df %>% group_by(country) %>% do(mod = lm(BirthRate ~ US., data = .))
Run Code Online (Sandbox Code Playgroud)
然后,如果您想对每个拟合模型执行ANOVA,您可以使用它 rowwise
models %>% rowwise %>% do(anova(.$mod))
Run Code Online (Sandbox Code Playgroud)
但是结果再次被强制转换为数据框,并且与执行操作不完全相同lapply(models$mod, anova).
现在(即直到下一个版本dplyr),如果你需要将整个结果存储在一个列表中,你可以只使用dlplyfrom plyr,like plyr::dlply(df, "country", function(d) anova(lm(BirthRate ~ US., data = d))),当然如果你不是绝对必须使用dplyr你可以去@SvenHohenstein的答案无论如何,这似乎是一种更好的方式.