2014-09-23 70 views
5

我試着在不同的數據集上運行anova,但並不知道如何去做。我goolged,發現這是有用的:http://www.ats.ucla.edu/stat/r/pages/looping_strings.htmr和anova一起替換

hsb2 <- read.csv("http://www.ats.ucla.edu/stat/data/hsb2.csv") 
names(hsb2) 
varlist <- names(hsb2)[8:11] 
models <- lapply(varlist, function(x) { 
lm(substitute(read ~ i, list(i = as.name(x))), data = hsb2) 
}) 

我的什麼上面的代碼所做的就是創建了一個函數LM(),它適用於varlist中的每一個變量,它在每個人的線性迴歸的理解。

於是我想到用AOV代替LM將工作對我來說是這樣的:

aov(substitute(read ~ i, list(i = as.name(x))), data = hsb2) 

不過,我得到這個錯誤:

Error in terms.default(formula, "Error", data = data) : 
no terms component nor attribute 

我沒有哪裏的錯誤來自主意。請幫忙!

+3

這是一個相當複雜的方式來包含他們建議的變量。我可能會這樣做:'lm(as.formula(paste(「read〜」,x)),data = hsb2)@ – thelatemail 2014-09-23 05:25:22

+0

@RichardScriven:你想知道這是否是一個「永恆的九月」的例子本科生的謙虛能幹?) – 2014-09-23 05:55:01

+1

@BonddedDust我希望我仍然是本科生.. – olala 2014-09-23 13:38:01

回答

5

的問題是,substitute()返回表達式,不是一個公式。我認爲@ thelatemail的建議

lm(as.formula(paste("read ~",x)), data = hsb2) 

是一個很好的解決方法。另外,您可以評估表達

models <- lapply(varlist, function(x) { 
    aov(eval(substitute(read ~ i, list(i = as.name(x)))), data = hsb2) 
}) 

得到公式我想這取決於你想以後用的型號列表做什麼。做

models <- lapply(varlist, function(x) { 
    eval(bquote(aov(read ~ .(as.name(x)), data = hsb2))) 
}) 

給出了一個「清潔」call屬性爲每個結果。

+0

你不應該同時需要'bquote'和'substitute' - 選擇一個!例如'eval(bquote(aov(read〜。(as.name(x)),data = hsb2)))' – hadley 2014-09-23 17:25:44

+0

Thanks @hadley。不知道我爲什麼很傻。我已根據您的評論進行更新。 – MrFlick 2014-09-23 18:18:04

+0

「替代」或「bquote」都不會返回表達式。通常他們會回電話。 – 2014-09-23 22:03:54

5

這應該這樣做。 varlist向量將逐個傳遞給函數,並且該列將被傳遞。 lm函數將只會看到一個兩列數據框,並且每次「讀」列都將是因變量。無需花哨取代:

models <- sapply(varlist, function(x) { 
lm(read ~ ., data = hsb2[, c("read", x) ]) 
}, simplify=FALSE) 

> summary(models[[1]]) # The first model. Note the use of "[[" 

Call: 
lm(formula = read ~ ., data = hsb2[, c("read", x)]) 

Residuals: 
    Min  1Q Median  3Q  Max 
-19.8565 -5.8976 -0.8565 5.5801 24.2703 

Coefficients: 
      Estimate Std. Error t value Pr(>|t|)  
(Intercept) 18.16215 3.30716 5.492 1.21e-07 *** 
write  0.64553 0.06168 10.465 < 2e-16 *** 
--- 
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1 

Residual standard error: 8.248 on 198 degrees of freedom 
Multiple R-squared: 0.3561, Adjusted R-squared: 0.3529 
F-statistic: 109.5 on 1 and 198 DF, p-value: < 2.2e-16 

對於所有型號::

lapply(models, summary) 
+0

不錯。使用'sapply(...,simplify = FALSE)'而不是'lapply'也會保留這個名字,並且允許你像'models $ write'這樣的子集合。 – thelatemail 2014-09-23 05:53:01

+0

好的mod。將編輯。 – 2014-09-23 05:59:29

+0

清除要用'lapply()'堅持,然後命名結果。 – hadley 2014-09-23 17:27:25

4

akrun借我的回答那天晚上,現在我(部分)借用他的。

do.call將變量放入call輸出中,以便正確讀取。這是簡單迴歸的一般功能。

doModel <- function(col1, col2, data = hsb2, FUNC = "lm") 
{ 
    form <- as.formula(paste(col1, "~", col2)) 
    do.call(FUNC, list(form, substitute(data))) 
}  

lapply(varlist, doModel, col1 = "read") 
# [[1]] 
# 
# Call: 
# lm(formula = read ~ write, data = hsb2) 
# 
# Coefficients: 
# (Intercept)  write 
#  18.1622  0.6455 
# 
# 
# [[2]] 
# 
# Call: 
# lm(formula = read ~ math, data = hsb2) 
# 
# Coefficients: 
# (Intercept)   math 
#  14.0725  0.7248 
# 
# ... 
# ... 
# ... 

注:由於thelatemail提到在他的評論

sapply(varlist, doModel, col1 = "read", simplify = FALSE) 

將保持名稱列表中,也允許list$name子集。

+0

+1確認:-) – akrun 2014-09-23 09:45:04

+0

感謝您的解釋! – olala 2014-09-23 19:50:24